home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 4 / Meeting Pearls Vol. IV (1996)(GTI - Schatztruhe)[!].iso / Pearls / dev / Misc / Robodoc / Source / robodoc.c < prev    next >
C/C++ Source or Header  |  1996-07-10  |  88KB  |  2,990 lines

  1. /****h* Autodoc/RoboDoc.c [3.0i]
  2.  * NAME
  3.  *   RoboDoc.c -- AutoDoc formatter
  4.  * COPYRIGHT
  5.  *   (c) 1994-1996  Maverick Software Development
  6.  *   This software is public domain and can be freely redistributed as
  7.  *   long as it is in its original state.
  8.  * FUNCTION
  9.  *   RoboDoc.c is intended to be a replacement for the original AutoDocs
  10.  *   program.  RoboDoc.c will extract the procedure comment headers
  11.  *   from a source file, and put them into a separate documentation file.
  12.  *   There are five different file output formats:
  13.  *       ASCII
  14.  *       HTML (HyperText Markup Langauge) -- mainly used on the Internet;
  15.  *           thus the files can be viewed with a normal HTML viewer/browser
  16.  *       AmigaGuide -- this format can be viewed by AmigaGuide (Amiga only)
  17.  *       LaTeX - as input to LaTeX to produce .dvi files
  18.  *       RTF (Rich Text Format) -- as input to the Help compiler (Windows only)
  19.  * AUTHOR
  20.  *   Frans Slothouber:  <slothoub@xs4all.nl>.
  21.  *     Source code and additional extensions
  22.  *     from version 2.0 and up.
  23.  *
  24.  *   Jacco van Weert: <weertj@IAehv.nl>
  25.  *     Original idea and program.
  26.  *
  27.  *   Bernd Koesling:  <KOESSI@CHESSY.aworld.de>
  28.  *     Bug fixes, functional improvements, code cleanup.
  29.  *
  30.  *   Anthon Pang:  <apang@mindlink.net>
  31.  *     RTF support, Bug fixes.
  32.  *
  33.  * CREATION DATE
  34.  *   20-Dec-94
  35.  * MODIFICATION HISTORY
  36.  *   Modifications by Jacco van Weert.
  37.  *     19-Jan-95     -  v0.8:   First test beta-version
  38.  *     26-Jan-95     -  v0.92:  2nd test beta-version
  39.  *     2-Feb-95      -  v0.93:  Mungwall hit, solved.
  40.  *                              When item headers, are also available
  41.  *                              in body then parts are duplicated solved.
  42.  *     Mar-95        -  v1.0a:  Final version
  43.  *     2-Apr-95      -  v1.0b:  Bug fixes
  44.  *                              Procedure header search bug solved.
  45.  *                              Print 'created procedure' text
  46.  *     20-Apr-95     -  v1.1a:  INTERNALONLY option added.
  47.  *                              Sort problem solved.
  48.  *   Modifications by FNC Slothouber.
  49.  *     10-May-1995 -  v2.0a  * Program completely rewritten
  50.  *                           * added SOURCE item and LaTeX output.
  51.  *                           * added TAB converter.
  52.  *     11-May-1995 -  v2.0b  * Accepts headers that start with
  53.  *                             any sequence of non-spaces.
  54.  *                             RoboDoc should work with any
  55.  *                             type of programming language now.
  56.  *     12-May-1995 -  v2.0c  * Bug fixes.
  57.  *     15-May-1995 -  v2.0d  * New Defaults file.
  58.  *                           * Added Verbose option.
  59.  *     24-May-1995 -  v2.0e  * Fixed a bug that cause the
  60.  *                             CleanUp Routine to lock up.
  61.  *                           * Improved the HTML output,
  62.  *                             should work faster now.
  63.  *   Modifications by Koessi
  64.  *     01-Aug-1995  - v2.0?  * more robust parsing, less enforcer-hits
  65.  *                           * removed self-referencing links !
  66.  *                           * remarked most changes with *koessi*
  67.  *                           * added GoldEd-foldmarks
  68.  *                           * compiled successfully with SAS-C 6.3
  69.  *     07-Aug-1995   -       * automated foldmarks "\***"
  70.  *                           ! GoldEd's foldmarks == RoboDoc marker !
  71.  *                           * quoted source parsing enhanced
  72.  *     08-Aug-1995   -       * a lot of while instead of for
  73.  *                           * a lot of switch() instead of ifelse
  74.  *                           * version defined
  75.  *                           * RB_Say, RB_Panic now useable like printf()
  76.  *                             new formats for nearly all output-strings
  77.  *                           * char *whoami is global copy of argv[0]
  78.  *                           * BOLD <- MAKE_LARGE && AMIGAGUIDE
  79.  *                           * succesfully compiled&tested on HPUX
  80.  *                           (HP9000/800)
  81.  *                           * optimized listfunctions
  82.  *                           * encapsulated header- and link-
  83.  *                             allocating and freeing
  84.  *                           * RB_Find_Function_Name() replaced
  85.  *                             with RB_FilePart()
  86.  *  Modifications by FNC Slothouber.
  87.  *    18-Aug-1995   -  v3.0  * New scanner that searches for
  88.  *                             a set default markers that define
  89.  *                             what is a comment or what is not
  90.  *                             and that define what or what is not
  91.  *                             a header/end marker.
  92.  *                           * Added Beast Support
  93.  *    27-Aug-1995   - v3.0b  * Fixed a bug with the defaults file
  94.  *                           * Improved search algorithm
  95.  *                             RoboDoc is now 5.8 times faster.
  96.  *    06-Sep-1995   - v3.0c  * Bug fixes
  97.  *    08-Oct-1995   - v3.0d  * Bug fixes
  98.  *    04-Feb-1996   - v3.0e  * fixed the problem with the TOC
  99.  *                             that included links to headers that
  100.  *                             were not selected. (i.e internal)
  101.  *    Modifications by apang
  102.  *    08-Mar-1996   - v3.0f  * Cleaner build for Borland C++ 4.52
  103.  *                           * Added more markers (C++, Pascal, Modula-2, COBOL)
  104.  *                           * Added more item types/names
  105.  *                           * Added #defines for the preamble (COMMENT_ROBODOC
  106.  *                             and COMMENT_COPYRIGHT)
  107.  *                           * BLANK_HEADER for detection of asterisk'd lines
  108.  *                           * RB_Say() the GENERIC header warning instead of
  109.  *                             using printf()
  110.  *                           * Indents SOURCE body in output
  111.  *                           * ASCII respects the TOC flag; removed extraneous
  112.  *                             newline after formfeed (so it's more like AutoDoc)
  113.  *                           * HTML output fixed to handle '<', '>', and '&'
  114.  *                           * LaTeX attributes and '%' handling added;
  115.  *                             fancied up the output a bit
  116.  *                           * RTF support added
  117.  *                           * Changed some fprintf()'s to fputc()'s for
  118.  *                             potentially lower overhead
  119.  *                           * Fixed line eater bug
  120.  *                           * More general fix to the TOC problem of including
  121.  *                             internal links when it wasn't selected
  122.  *  Modifications by FNC Slothouber.
  123.  *    01-April-1996  - v3.0h * Added ';' to > and < so lynx also recog. them
  124.  *                           * Fancied up the HTML output.
  125.  *    10-July-1996   - v3.0i * Bug Fix.  Both the options INTERNAL
  126.  *                             and INTERNALONLY did not work correctly.
  127.  *
  128.  * NOTES
  129.  *   Has been succesfully compiled:
  130.  *     On an Amiga with SAS/C and DICE C (Amiga 1200)
  131.  *     On a Sun Sparc Station with gcc   (under SunOS 4.1)
  132.  *     On a Dec Alpha Station
  133.  *     Under HP/UX on a HP9000/800
  134.  * BUGS
  135.  *   - HTML output is not Lynx friendly -- attributes are applied
  136.  *     to leading white space =P ... solution: fix Lynx  >=)
  137.  *   - Can't get the escape character for @ to work in
  138.  *     AmigaGuide format.
  139.  *   Other bugs?
  140.  *     Catch them in a jar and send them to slothoub@xs4all.nl.
  141.  ****/
  142.  
  143. #include <stdio.h>
  144. #include <ctype.h>
  145. #include <stdlib.h>
  146. #include <string.h>
  147. #include <stdarg.h> /* for RB_Say() */
  148.  
  149. #include "robodoc.h"
  150.  
  151. #define RB_VERSION "3.0i"
  152.  
  153. static char RB_VER[] = "$VER: robodoc "RB_VERSION" (" __DATE__ ")";
  154.  
  155. #define COMMENT_ROBODOC \
  156.     "Generated with RoboDoc v" RB_VERSION " (" __DATE__ ")\n"
  157. #define COMMENT_COPYRIGHT \
  158.     "RoboDoc is copyright 1994--1996 by Maverick Software Development\n"
  159.  
  160. /****** RoboDoc.c/header_markers [3.0h]
  161.  * NAME
  162.  *   header_markers
  163.  * FUNCTION
  164.  *   These specify what robodoc will recognize as the beginning
  165.  *   of a header.
  166.  * SOURCE
  167.  */
  168.  
  169. char *header_markers[] = {
  170.     "/****",                    /* C, C++ */
  171.     "//****",                   /* C++ */
  172.     "(****",                    /* Pascal, Modula-2, B52 */
  173.     "{****",                    /* Pascal */
  174.     ";****",                    /* M68K assembler */
  175.     "****",                     /* M68K assembler */
  176.     "C     ****",               /* Fortran */
  177.     "REM ****",                 /* BASIC */
  178.     "%****",                    /* LaTeX, TeX, Postscript */
  179.     "      ****",               /* COBOL */
  180.     NULL } ;
  181.  
  182. /****/
  183.  
  184.  
  185. /****** RoboDoc.c/remark_markers [3.0h]
  186.  * NAME
  187.  *   remark_markers
  188.  * FUNCTION
  189.  *   These specify what robodoc will recognize as a comment marker.
  190.  * SOURCE
  191.  */
  192.  
  193. char *remark_markers[] = {
  194.     " *",                       /* C, C++, Pascal, Modula-2 */
  195.     "//",                       /* C++ */
  196.     "*",                        /* C, C++, M68K assembler, Pascal, Modula-2 */
  197.     ";*",                       /* M68K assembler */
  198.     ";",                        /* M68K assembler */
  199.     "C    ",                    /* Fortran */
  200.     "REM ",                     /* BASIC */
  201.     "%",                        /* LaTeX, TeX, Postscript */
  202.     "      *",                  /* COBOL */
  203.     NULL } ;
  204.  
  205. /****/
  206.  
  207.  
  208. /****** RoboDoc.c/end_markers [3.0h]
  209.  * NAME
  210.  *   end_markers
  211.  * FUNCTION
  212.  *   These specify what robodoc will recognize as the
  213.  *   end of a documentation header.
  214.  * SOURCE
  215.  */
  216.  
  217. char *end_markers[] = {
  218.     "/***",                     /* C, C++ */
  219.     "//***",                    /* C++ */
  220.     " ***",                     /* C, C++, Pascal, Modula-2 */
  221.     "{***",                     /* Pascal */
  222.     "(***",                     /* Pascal, Modula-2, B52 */
  223.     ";***",                     /* M68K assembler */
  224.     "***",                      /* M68K assembler */
  225.     "C     ***",                /* Fortran */
  226.     "REM ***",                  /* BASIC */
  227.     "%***",                     /* LaTeX, TeX, Postscript */
  228.     "      ***",                /* COBOL */
  229.     NULL } ;
  230.  
  231. /****/
  232.  
  233.  
  234. /* Header Types etc... */
  235.  
  236. enum { NO_HEADER = 0, MAIN_HEADER, GENERIC_HEADER, INTERNAL_HEADER, BLANK_HEADER } ;
  237.  
  238. /****** RoboDoc.c/output_mode [2.0]
  239.  * NAME
  240.  *   output_mode -- the mode of output
  241.  * FUNCTION
  242.  *   Controls which type of output will be generated.
  243.  * SOURCE
  244.  */
  245.  
  246. /* Output Modes */
  247.  
  248. enum { ASCII = 0, AMIGAGUIDE, HTML, LATEX, RTF, SIZE_MODES } ;
  249.  
  250. /* Reserved for Future Use */
  251.  
  252. enum { ANSI, GNUINFO, TROFF } ;
  253.  
  254.  
  255. /* Global Variable that defines the output mode */
  256.  
  257. int output_mode = ASCII;
  258.  
  259. /****/
  260.  
  261.  
  262. /****** RoboDoc.c/item_names [3.0g]
  263.  * NAME
  264.  *   item_names
  265.  * SYNOPSIS
  266.  *   char *item_names[]
  267.  * FUNCTION
  268.  *   used for strcmp() in RB_Get_Item_Type()
  269.  * AUTHOR
  270.  *   Koessi
  271.  * SEE ALSO
  272.  *   RB_Get_Item_Type(), item_attributes, item_attr_names
  273.  * SOURCE
  274.  */
  275.  
  276. char *item_names[] =
  277. {
  278.   NULL, "NAME", "COPYRIGHT", "SYNOPSIS",
  279.   "FUNCTION", "DESCRIPTION", "AUTHOR",
  280.   "CREATION DATE", "MODIFICATION HISTORY", "HISTORY",
  281.   "INPUTS", "ARGUMENTS", "OPTIONS", "PARAMETERS", "SWITCHES",
  282.   "OUTPUT", "SIDE EFFECTS", "RESULT", "RETURN VALUE",
  283.   "EXAMPLE", "NOTES", "DIAGNOSTICS",
  284.   "WARNINGS", "ERRORS", "BUGS", "TODO", "IDEAS",
  285.   "PORTABILITY", "SEE ALSO", "SOURCE",
  286.   "BEAST METHODS", "NEW METHODS",
  287.   "BEAST ATTRIBUTES", "NEW ATTRIBUTES",
  288.   NULL,
  289. };
  290.  
  291. /* Item Types */
  292. enum
  293. {
  294.   NO_ITEM = 0,  NAME_ITEM,  COPYRIGHT_ITEM,  SYNOPSIS_ITEM,
  295.   FUNCTION_ITEM,  DESCRIPTION_ITEM, AUTHOR_ITEM,
  296.   CREATION_DATE_ITEM,  MODIFICATION_HISTORY_ITEM,  HISTORY_ITEM,
  297.   INPUT_ITEM,  ARGUMENT_ITEM,  OPTION_ITEM,  PARAMETER_ITEM,  SWITCH_ITEM,
  298.   OUTPUT_ITEM,  SIDE_EFFECTS_ITEM,  RESULT_ITEM,  RETURN_VALUE_ITEM,
  299.   EXAMPLE_ITEM,  NOTE_ITEM,  DIAGNOSTICS_ITEM,
  300.   WARNING_ITEM,  ERROR_ITEM,  BUGS_ITEM,  TODO_ITEM,  IDEAS_ITEM,
  301.   PORTABILITY_ITEM,  SEE_ALSO_ITEM,  SOURCE_ITEM,
  302.   BEAST_METHODS,  NEW_METHODS,
  303.   BEAST_ATTRIBUTES,  NEW_ATTRIBUTES,  OTHER_ITEM,
  304.   NUMBER_OF_ITEMS
  305. };
  306.  
  307. /****/
  308.  
  309.  
  310. /****** RoboDoc.c/item_attributes [3.0h]
  311.  * NAME
  312.  *   item_attributes -- attributes of the various items
  313.  * FUNCTION
  314.  *   links each item type with a text attribute.
  315.  * SEE ALSO
  316.  *   RB_Get_Item_Type(), item_names, item_attr_names
  317.  * SOURCE
  318.  */
  319.  
  320. enum
  321. {
  322.   MAKE_NORMAL = -1,  MAKE_LARGE, MAKE_ITALICS, MAKE_NON_PROP, MAKE_SMALL,
  323.   MAKE_BOLD, MAKE_UNDERLINE, MAKE_SHINE, MAKE_HIGH, SIZE_ATTRIBUTES
  324. };
  325.  
  326. #define ITEM_NAME_LARGE_FONT (1<<0)
  327. #define TEXT_BODY_LARGE_FONT (1<<(MAKE_LARGE     + 1))
  328. #define TEXT_BODY_ITALICS    (1<<(MAKE_ITALICS   + 1))
  329. #define TEXT_BODY_NON_PROP   (1<<(MAKE_NON_PROP  + 1))
  330. #define TEXT_BODY_SMALL_FONT (1<<(MAKE_SMALL     + 1))
  331. #define TEXT_BODY_BOLD       (1<<(MAKE_BOLD      + 1))
  332. #define TEXT_BODY_UNDERLINE  (1<<(MAKE_UNDERLINE + 1))
  333. #define TEXT_BODY_SHINE      (1<<(MAKE_SHINE     + 1))
  334. #define TEXT_BODY_HIGHLIGHT  (1<<(MAKE_HIGH      + 1))
  335.  
  336. long item_attributes[NUMBER_OF_ITEMS] =
  337. {
  338.   0                                    , /* NO_ITEM */
  339.   ITEM_NAME_LARGE_FONT|TEXT_BODY_SHINE , /* NAME_ITEM */
  340.   ITEM_NAME_LARGE_FONT                 , /* COPYRIGHT_ITEM */
  341.   ITEM_NAME_LARGE_FONT                 , /* SYNOPSIS_ITEM */
  342.   ITEM_NAME_LARGE_FONT                 , /* FUNCTION_ITEM */
  343.   ITEM_NAME_LARGE_FONT                 , /* DESCRIPTION_ITEM */
  344.   ITEM_NAME_LARGE_FONT|TEXT_BODY_BOLD  , /* AUTHOR_ITEM */
  345.   ITEM_NAME_LARGE_FONT|TEXT_BODY_BOLD  , /* CREATION_DATE_ITEM */
  346.   ITEM_NAME_LARGE_FONT                 , /* MODIFICATION_HISTORY_ITEM */
  347.   ITEM_NAME_LARGE_FONT                 , /* HISTORY_ITEM */
  348.   ITEM_NAME_LARGE_FONT                 , /* INPUT_ITEM */
  349.   ITEM_NAME_LARGE_FONT                 , /* ARGUMENT_ITEM */
  350.   ITEM_NAME_LARGE_FONT                 , /* OPTION_ITEM */
  351.   ITEM_NAME_LARGE_FONT                 , /* PARAMETER_ITEM */
  352.   ITEM_NAME_LARGE_FONT                 , /* SWITCH_ITEM */
  353.   ITEM_NAME_LARGE_FONT                 , /* OUTPUT_ITEM */
  354.   ITEM_NAME_LARGE_FONT                 , /* SIDE_EFFECTS_ITEM */
  355.   ITEM_NAME_LARGE_FONT                 , /* RESULT_ITEM */
  356.   ITEM_NAME_LARGE_FONT                 , /* RETURN_VALUE_ITEM */
  357.   ITEM_NAME_LARGE_FONT                 , /* EXAMPLE_ITEM */
  358.   ITEM_NAME_LARGE_FONT|TEXT_BODY_SHINE , /* NOTE_ITEM */
  359.   ITEM_NAME_LARGE_FONT                 , /* DIAGNOSTICS_ITEM */
  360.   ITEM_NAME_LARGE_FONT                 , /* WARNING_ITEM */
  361.   ITEM_NAME_LARGE_FONT                 , /* ERROR_ITEM */
  362.   ITEM_NAME_LARGE_FONT|TEXT_BODY_SHINE , /* BUGS_ITEM */
  363.   ITEM_NAME_LARGE_FONT                 , /* TODO_ITEM */
  364.   ITEM_NAME_LARGE_FONT                 , /* IDEAS_ITEM */
  365.   ITEM_NAME_LARGE_FONT                 , /* PORTABILITY_ITEM */
  366.   ITEM_NAME_LARGE_FONT                 , /* SEE_ALSO_ITEM */
  367.   ITEM_NAME_LARGE_FONT                 , /* SOURCE_ITEM */
  368.   ITEM_NAME_LARGE_FONT                 , /* BEAST METHODS */
  369.   ITEM_NAME_LARGE_FONT                 , /* NEW METHODS */
  370.   ITEM_NAME_LARGE_FONT                 , /* BEAST ATTRIBUTES */
  371.   ITEM_NAME_LARGE_FONT                 , /* NEW ATTRIBUTES" */
  372.   0                                      /* OTHER_ITEM */
  373. };
  374.  
  375. /****/
  376.  
  377.  
  378. /****** RoboDoc.c/item_attr_names [3.0h]
  379.  * NAME
  380.  *   item_attr_names
  381.  * SYNOPSIS
  382.  *   char *item_attr_names[]
  383.  * FUNCTION
  384.  *   used for strcmp() in RB_Get_Item_Attr()
  385.  * AUTHOR
  386.  *   Koessi
  387.  * SEE ALSO
  388.  *   RB_Get_Item_Attr(), item_attributes, item_names
  389.  * SOURCE
  390.  */
  391.  
  392. char *item_attr_names[] =
  393. {
  394. /*  "NORMAL", */
  395.   "LARGE",  "ITALICS",  "NONPROP",  "SMALL",  "BOLD",
  396.   "UNDERLINE",   "SHINE",  "HIGHLIGHT"
  397. };
  398.  
  399. /* ASCII AMIGAGUIDE HTML LATEX RTF */
  400.  
  401. char *att_start_command[SIZE_ATTRIBUTES][SIZE_MODES] =
  402. {
  403.   "", "@{b}"           , "<FONT SIZE=+1>" , "{\\large "   , "\\par\\fs28 ", /* Large Font */
  404.   "", "@{i}"           , "<I>"           , "{\\it "      , "\\i1 "       , /* Italics. */
  405.   "", ""               , ""              , ""            , ""            , /* NON-Proportional font. */
  406.   "", ""               , "<FONT SIZE=-1>", "{\\small "   , "\\fs16 "     , /* Small Font. */
  407.   "", "@{b}"           , "<B>"           , "{\\bf "      , "\\b1 "       , /* Bold. */
  408.   "", "@{u}"           , "<U>"           , "\\underline{", "\\ul1 "      , /* Underline */
  409.   "", "@{fg shine}"    , "<EM>"          , "{\\em "      , ""            , /* Shine */
  410.   "", "@{fg highlight}", "<EM>"          , "{\\em "      , ""              /* Highlight */
  411. };
  412.  
  413. char *att_stop_command[SIZE_ATTRIBUTES][SIZE_MODES] =
  414. {
  415.   "", "@{ub}"          , "</FONT>"       , "}"           , "\\fs20\\line ", /* Large Font */
  416.   "", "@{ui}"          , "</I>"          , "}"           , "\\i0 "        , /* Italics. */
  417.   "", ""               , ""              , ""            , ""             , /* NON-Proportional font. */
  418.   "", ""               , "</FONT>"       , "}"           , "\\fs20 "      , /* Small Font. */
  419.   "", "@{ub}"          , "</B>"          , "}"           , "\\b0 "        , /* Bold. */
  420.   "", "@{uu}"          , "</U>"          , "}"           , "\\ul0 "       , /* Underline */
  421.   "", "@{fg text}"     , "</EM>"         , "}"           , ""             , /* Shine */
  422.   "", "@{fg text}"     , "</EM>"         , "}"           , ""               /* Highlight */
  423. };
  424.  
  425. /****/
  426.  
  427.  
  428. /****** RoboDoc.c/course_of_action [2.0]
  429.  * NAME
  430.  *   course_of_action
  431.  * FUNCTION
  432.  *   Global Variable that defines the course of action.
  433.  * SOURCE
  434.  */
  435.  
  436. #define DO_SORT             (1<<0)
  437. #define DO_MAKE_XREFS       (1<<1)
  438. #define DO_USE_XREFS        (1<<2)
  439. #define DO_TOC              (1<<3)
  440. #define DO_MAKE_DOCUMENT    (1<<4)
  441. #define DO_INCLUDE_INTERNAL (1<<5)
  442. #define DO_INTERNAL_ONLY    (1<<6)
  443. #define DO_TELL             (1<<7)
  444.  
  445. int course_of_action = DO_MAKE_DOCUMENT;
  446.  
  447. /****/
  448.  
  449.  
  450. /****** RoboDoc.c/line_buffer [2.0]
  451.  * NAME
  452.  *   line_buffer -- global line buffer
  453.  * FUNCTION
  454.  *   Temporary storage area for lines
  455.  *   that are read from an input file.
  456.  * SOURCE
  457.  */
  458.  
  459. #define MAX_LINE_LEN 512
  460. char line_buffer[MAX_LINE_LEN];
  461.  
  462. /****/
  463.  
  464.  
  465. /****** RoboDoc.c/line_number [2.0]
  466.  * NAME
  467.  *   line_number -- global line counter
  468.  * FUNCTION
  469.  *   count the lines that are read from an input file.
  470.  * AUTHOR
  471.  *   Koessi
  472.  * SOURCE
  473.  */
  474.  
  475. int line_number = 0;
  476.  
  477. /****/
  478.  
  479.  
  480. /****** RoboDoc.c/use [3.0h]
  481.  * NAME
  482.  *   use -- usage string
  483.  * FUNCTION
  484.  *   inform the user how to use me
  485.  * AUTHOR
  486.  *   Koessi
  487.  * SOURCE
  488.  */
  489.  
  490. char use[] =
  491.   "\nRoboDoc v" RB_VERSION ", autodocs formatter\n\n"
  492.   "(c) " __DATE__ ", Maverick Software Development\n"
  493.   "Original idea and program:  Jacco van Weert   <weertj@iaehv.nl>\n"
  494.   "Version 2.0 and up:         Frans Slothouber  <slothoub@xs4all.nl>\n"
  495.   "RTF support:                Anthon Pang       <apang@mindlink.net>\n"
  496.   "\nFORMAT\n"
  497.   "  robodoc filename docfilename\n"
  498.   "\nIn addition you can use one or more of the following options:\n"
  499.   "  GENXREF <xref_filename>  - to generate an xref file.\n"
  500.   "  XREF <xreflist_filename> - if you want to use xref files to create\n"
  501.   "                             cross links\n"
  502.   "  TABSIZE <nr_sp>          - convert each TAB to nr_sp of spaces.\n"
  503.   "  TOC          - a table of contents will be generated.\n"
  504.   "  SORT         - the headers will be sorted.\n"
  505.   "  -v           - tell robodoc to tell you all about it.\n"
  506.   "  INTERNAL     - headers marked internal will also be included.\n"
  507.   "  INTERNALONLY - only headers marked internal will be included.\n"
  508.   "\nThe type of output is selected with one of the following switches:\n"
  509.   "  ASCII, GUIDE, HTML, LATEX, or RTF\n"
  510.   "\nThe following abbreviations are also allowed:\n"
  511.   "  TOC = -t  XREF = -x   SORT = -s  INTERNAL = -i \n"
  512.   "  GENXREF = -g  INTERNALONLY = -io  TABSIZE = -ts\n";
  513.  
  514. /****/
  515.  
  516.  
  517. /* Global variables & prototypes */
  518.  
  519. char *whoami = NULL; /* me,myself&i */
  520. int tab_size = 8;
  521.  
  522. struct RB_header *first_header = NULL;
  523. struct RB_header *last_header  = NULL;
  524. struct RB_link   *first_link   = NULL;
  525.  
  526. int header_index_size = 0 ;
  527. struct RB_header **header_index = NULL ;
  528.  
  529. int link_index_size = 0 ;
  530. struct RB_link   **link_index   = NULL ;
  531.  
  532. FILE *document = NULL;
  533. FILE *dest_doc = NULL;
  534. FILE *xreffiles_file = NULL;
  535. FILE *xref_file = NULL;
  536.  
  537. void RB_Analyse_Document  (FILE *);
  538. void RB_Analyse_Xrefs     (FILE *);
  539. void RB_Analyse_Arguments (int, char **, char **, char **);
  540. void RB_Analyse_Defaults_File(void);
  541.  
  542. int RB_Find_Marker     (FILE *);
  543. int RB_Find_End_Marker (FILE *, int *);
  544. int RB_Find_Item       (char **, char **);
  545. char *RB_Find_Header_Name(void);
  546.  
  547. void RB_Generate_xrefs         (FILE * dest_doc, char *, char *) ;
  548. void RB_Generate_Documentation (FILE *, char *, char *) ;
  549. void RB_Generate_Item_Doc      (FILE *, char *, char *, char *, char *, int) ;
  550. void RB_Generate_Item_Body     (FILE *, char *, char *, char *, char *, int) ;
  551. void RB_Generate_Header_Name   (FILE *, char *) ;
  552. void RB_Generate_Item_Name     (FILE *, int) ;
  553. void RB_Generate_Doc_Start     (FILE *, char *, char *) ;
  554. void RB_Generate_Doc_End       (FILE *, char *) ;
  555. void RB_Generate_Header_Start  (FILE *, struct RB_header *) ;
  556. void RB_Generate_Header_End    (FILE *, struct RB_header *) ;
  557. void RB_Close_The_Shop         (void);
  558. void RB_Make_Index_Tables      (void) ;
  559.  
  560. void RB_Remove_From_List (struct RB_header **, struct RB_header *);
  561. void RB_Insert_In_List   (struct RB_header **, struct RB_header *);
  562. void RB_Slow_Sort        (void);
  563. void RB_Add_Link         (void);
  564. int  RB_Find_Link        (char *, char **, char **);
  565.  
  566. char *RB_FilePart      (char *);
  567. int   RB_Get_Item_Type (char *);
  568. int   RB_WordLen       (char *);
  569. char *RB_StrDup        (char *);
  570. char *RB_CookStr       (char *);
  571.  
  572. struct RB_header *RB_Alloc_Header(void);
  573. void   RB_Free_Header(struct RB_header *);
  574.  
  575. struct RB_link *RB_Alloc_Link(char *, char *);
  576. void   RB_Free_Link(struct RB_link *);
  577.  
  578. void   RB_Say   (char *, ...);
  579. void   RB_Panic (char *, ...);
  580.  
  581. char *RB_Skip_Remark_Marker (char *line_buffer) ;
  582.  
  583. /********/
  584.  
  585.  
  586. /****i* RoboDoc.c/_main [2.0d]
  587.  * NAME
  588.  *   _main -- Entry point of RoboDoc.c
  589.  * SYNOPSIS
  590.  *   main (int argc, char **argv)
  591.  * FUNCTION
  592.  *   Get and parse the arguments.
  593.  *   Analyse document.
  594.  * SOURCE
  595.  */
  596.  
  597. int main(int argc, char **argv)
  598. {
  599.   char *file_with_xrefs, *output_file_for_xrefs ;
  600.  
  601.   whoami = argv[0] ;  /* global me,myself&i */
  602.   if ((argc < 3) || (*argv[1] == '?'))
  603.   {
  604.     printf(use);
  605.   }
  606.   else
  607.   {
  608.     RB_Analyse_Arguments(argc, argv, &file_with_xrefs, &output_file_for_xrefs);
  609.  
  610.     RB_Say("Analysing Defaults File\n") ;
  611.     RB_Analyse_Defaults_File () ;
  612.  
  613.     RB_Say("trying to open source file \"%s\"\n", argv[1]);
  614.     if ((document = fopen(argv[1], "r")) != NULL)
  615.     {
  616.       RB_Say("analysing source file \"%s\"\n", argv[1]);
  617.       RB_Analyse_Document(document);
  618.  
  619.       if (course_of_action & DO_SORT)
  620.       {
  621.         RB_Say("sorting headers\n");
  622.         RB_Slow_Sort();
  623.       }
  624.       if ((course_of_action & DO_USE_XREFS) && file_with_xrefs)
  625.       {
  626.         if ((xreffiles_file = fopen(file_with_xrefs, "r")) != NULL)
  627.         {
  628.           RB_Analyse_Xrefs(xreffiles_file);
  629.         }
  630.         else
  631.         {
  632.           RB_Panic("can't open file with xref files \"%s\"\n", file_with_xrefs);
  633.         }
  634.       }
  635.       if (course_of_action & DO_MAKE_DOCUMENT)
  636.       {
  637.         RB_Say("trying to open destination file \"%s\"\n", argv[2]);
  638.         if ((dest_doc = fopen(argv[2], "w")) != NULL)
  639.         {
  640.           RB_Say("generating documentation\n");
  641.           RB_Generate_Documentation(dest_doc, RB_FilePart(argv[1]), RB_FilePart(argv[2]));  /* additional function *koessi */
  642.           fclose(dest_doc);
  643.           dest_doc = NULL;
  644.         }
  645.         else RB_Panic("can't open destination file \"%s\"\n", argv[2]);
  646.       }
  647.       if ((course_of_action & DO_MAKE_XREFS) && output_file_for_xrefs)
  648.       {
  649.         RB_Say("trying to open xref destination file \"%s\"\n", output_file_for_xrefs);
  650.         if ((dest_doc = fopen(output_file_for_xrefs, "w")) != NULL)
  651.         {
  652.           RB_Say("generating xref destination file \"%s\"\n", output_file_for_xrefs);
  653.           RB_Generate_xrefs(dest_doc, argv[1], argv[2]);
  654.           fclose(dest_doc);
  655.           dest_doc = NULL;
  656.         }
  657.         else RB_Panic("can't open xref destination file \"%s\"\n", output_file_for_xrefs);
  658.       }
  659.     }
  660.     else RB_Panic("can't open source file \"%s\"\n", argv[1]);
  661.   }
  662.   RB_Say("Ready\n");
  663.   RB_Close_The_Shop();
  664.   return (0);
  665. }
  666.  
  667. /*** main ***/
  668.  
  669.  
  670. /****** RoboDoc.c/RB_FilePart [2.0x]
  671.  * NAME
  672.  *   RB_FilePart
  673.  * SYNOPSIS
  674.  *   char *RB_FilePart(char *file_name)
  675.  * FUNCTION
  676.  *   return the basename (like Amiga/Dos/FilePart())
  677.  * NOTES
  678.  *   koessi
  679.  * SEE ALSO
  680.  * SOURCE
  681.  */
  682.  
  683. char *RB_FilePart(char *file_name)
  684. {
  685.   char *cur_char;
  686.   char c;
  687.  
  688.   if ((cur_char = file_name) != NULL)
  689.   {
  690.     for (; (c = *cur_char) != '\0'; ++cur_char)
  691.     {
  692.       if ((c == '/') || (c == ':'))
  693.       {
  694.         ++cur_char;
  695.         while ('/' == *cur_char)
  696.           ++cur_char;
  697.  
  698.         if (*cur_char)
  699.           file_name = cur_char;
  700.       }
  701.     }
  702.   }
  703.   return (file_name);
  704. }
  705.  
  706. /*** RB_File_Part ***/
  707.  
  708.  
  709. /****** RoboDoc.c/RB_Get_Item_Type [3.0b]
  710.  * NAME
  711.  *   RB_Get_Item_Type -- shortcut
  712.  * SYNOPSIS
  713.  *   int RB_Get_Item_Type( char *cmp_name )
  714.  * FUNCTION
  715.  *   return the item_type represented by the given string
  716.  * INPUTS
  717.  *   char *cmp_name          -- item_name to evaluate
  718.  * RESULT
  719.  *   int                     -- the right item_type or NO_ITEM
  720.  * NOTES
  721.  *   uses global char *item_names[]
  722.  * AUTHOR
  723.  *   Koessi
  724.  * SEE ALSO
  725.  *   RB_Analyse_Defaults_File(), RB_Get_Item_Attr()
  726.  * SOURCE
  727.  */
  728.  
  729. int RB_Get_Item_Type(char *cmp_name)
  730. {
  731.   int  item_type;
  732.   for (item_type = NAME_ITEM; item_type < OTHER_ITEM; ++item_type)
  733.   {
  734.     if (!strncmp(item_names[item_type], cmp_name, strlen(item_names[item_type])))
  735.       return(item_type);
  736.   }
  737.   return(NO_ITEM);
  738. }
  739.  
  740. /*** RB_Get_Item_Type ***/
  741.  
  742.  
  743. /****** RoboDoc.c/RB_Get_Item_Attr [3.0b]
  744.  *
  745.  * NAME
  746.  *   RB_Get_Item_Attr -- shortcut
  747.  * SYNOPSIS
  748.  *   int RB_Get_Item_Attr( char *cmp_name )
  749.  * FUNCTION
  750.  *   return the item_attr represented by the given string
  751.  * INPUTS
  752.  *   char *cmp_name  -- item_attr_name to evaluate
  753.  * RESULT
  754.  *   int             -- the right item_attr or NULL
  755.  * NOTES
  756.  *   uses global char *item_attr_names[]
  757.  * AUTHOR
  758.  *   Koessi
  759.  * SEE ALSO
  760.  *   RB_Analyse_Defaults_File(), RB_Get_Item_Type()
  761.  * SOURCE
  762.  */
  763.  
  764. int RB_Get_Item_Attr(char *cmp_name)
  765. {
  766.   int  item_attr;
  767.   for (item_attr = MAKE_LARGE; item_attr < SIZE_ATTRIBUTES; ++item_attr)
  768.     if (!strcmp(item_attr_names[item_attr], cmp_name))
  769.       return(item_attr);
  770.   if (strcmp("NORMAL", cmp_name))
  771.   {
  772.     printf ("%s: Warning unknown attribute [%s] in defaults file.\n",whoami, cmp_name) ;
  773.   }
  774.   return(MAKE_NORMAL);
  775. }
  776.  
  777. /*** RB_Get_Item_Attr ***/
  778.  
  779.  
  780. /****** RoboDoc.c/RB_Analyse_Defaults_File [3.0b]
  781.  * NAME
  782.  *   RB_Analyse_Defaults_file -- read default from defaults file
  783.  * SYNOPSIS
  784.  *   RB_Analyse_Defaults_file
  785.  * FUNCTION
  786.  *   Read the default vaules from the default file.
  787.  * SEE ALSO
  788.  * SOURCE
  789.  */
  790.  
  791. void RB_Analyse_Defaults_File()
  792. {
  793.   FILE *defaults_file;
  794.  
  795.   if ((defaults_file = fopen("robodoc.defaults", "r")) != NULL)
  796.   {
  797.     while (!feof(defaults_file))
  798.     {
  799.       char *cur_char;
  800.       *line_buffer = '\0';
  801.  
  802.       fgets(line_buffer, MAX_LINE_LEN, defaults_file);
  803.  
  804.       if (*line_buffer != '\n')
  805.       {
  806.         int   item_type;
  807.         item_type = RB_Get_Item_Type(line_buffer);
  808.         if (item_type != NO_ITEM)
  809.         {
  810.           char *values ;
  811.  
  812.           item_attributes[item_type] = ITEM_NAME_LARGE_FONT ;
  813.  
  814.           cur_char = line_buffer + strlen(item_names[item_type]) ;
  815.           for (; *cur_char && isspace(*cur_char); cur_char++) ;
  816.  
  817.           while (*cur_char)
  818.           {
  819.             for (values = cur_char;
  820.                  *cur_char && !isspace(*cur_char);
  821.                  cur_char++) ;
  822.             if (*cur_char)
  823.             {
  824.               int item_attr;
  825.               *cur_char = '\0';
  826.               item_attr = RB_Get_Item_Attr(values) ;
  827.               if (item_attr != MAKE_NORMAL)
  828.               {
  829.                 RB_Say ("Default: %s = %s\n", item_names[item_type],
  830.                                               item_attr_names[item_attr]) ;
  831.                 item_attributes[item_type] |= (1<<(item_attr+1)) ;
  832.               }
  833.             }
  834.             for (cur_char++; *cur_char && isspace(*cur_char); cur_char++) ;
  835.           }
  836.         }
  837.       }
  838.     }
  839.     fclose(defaults_file);
  840.   }
  841.   else
  842.   {
  843.     printf("%s: WARNING, robodoc.defaults file was not found.\n", whoami);
  844.     printf("\t\tyou should really use one.\n");
  845.   }
  846. }
  847.  
  848. /*** RB_Analyse_Defaults_File ***/
  849.  
  850.  
  851. /****** RoboDoc.c/RB_Analyse_Arguments [3.0h]
  852.  * NAME
  853.  *   RB_Analyse_Arguments
  854.  * SYNOPSIS
  855.  *   RB_Analyse_Arguments (argc, argv, file_with_xrefs,
  856.  *                         output_file_for_xrefs)
  857.  *   RB_Analyse_Arguments (int, char **, char **, char **)
  858.  * FUNCTION
  859.  *   Get and parse the arguments.
  860.  * SEE ALSO
  861.  * SOURCE
  862.  */
  863.  
  864. void RB_Analyse_Arguments(int argc, char **argv,
  865.                           char **file_with_xrefs,
  866.                           char **output_file_for_xrefs)
  867. {
  868.   char **parameter;
  869.   int parameter_nr;
  870.  
  871.   for (parameter_nr = argc - 3, parameter = argv + 3;
  872.        parameter_nr > 0;
  873.        parameter++, parameter_nr--)
  874.   {
  875.     char *cur_char ;
  876.  
  877.     for (cur_char = *parameter ; *cur_char ; cur_char++)
  878.         *cur_char = toupper(*cur_char) ;
  879.  
  880.     if      (!strcmp(*parameter, "HTML"))  output_mode = HTML;
  881.     else if (!strcmp(*parameter, "GUIDE")) output_mode = AMIGAGUIDE;
  882.     else if (!strcmp(*parameter, "LATEX")) output_mode = LATEX;
  883.     else if (!strcmp(*parameter, "ASCII")) output_mode = ASCII;
  884.     else if (!strcmp(*parameter, "RTF"))   output_mode = RTF;
  885.     else if (!strcmp(*parameter, "SORT") ||  !strcmp(*parameter, "-S"))
  886.       course_of_action |= DO_SORT;
  887.     else if (!strcmp(*parameter, "INTERNAL") || !strcmp(*parameter, "-I"))
  888.       course_of_action |= DO_INCLUDE_INTERNAL;
  889.     else if (!strcmp(*parameter, "INTERNALONLY") || !strcmp(*parameter, "-IO"))
  890.       course_of_action |= DO_INTERNAL_ONLY;
  891.     else if (!strcmp(*parameter, "TOC") || !strcmp(*parameter, "-T"))
  892.       course_of_action |= DO_TOC;
  893.     else if (!strcmp(*parameter, "-V")) course_of_action |= DO_TELL;
  894.     else if (!strcmp(*parameter, "XREF") || !strcmp(*parameter, "-X"))
  895.     {
  896.       if (--parameter_nr)
  897.       {
  898.         parameter++ ;
  899.         *file_with_xrefs = *parameter ;
  900.         RB_Say ("XREF=\"%s\"\n", *file_with_xrefs) ;
  901.         course_of_action |= DO_USE_XREFS ;
  902.       }
  903.       else RB_Panic("you must specify a xref file with the XREF option\n");
  904.     }
  905.     else if (!strcmp(*parameter, "TABSIZE") || !strcmp(*parameter, "-TS"))
  906.     {
  907.       if (--parameter_nr)
  908.       {
  909.         parameter++ ;
  910.         tab_size = atoi(*parameter);
  911.       }
  912.       else
  913.       {
  914.         RB_Panic("you must specify the number of spaces with the TABSIZE option\n");
  915.       }
  916.     }
  917.     else if (!strcmp(*parameter, "GENXREF") || !strcmp(*parameter, "-G"))
  918.     {
  919.       if (--parameter_nr)
  920.       {
  921.         ++parameter;
  922.         *output_file_for_xrefs = *parameter;
  923.         RB_Say("GENXREF=\"%s\"\n", *output_file_for_xrefs);
  924.         course_of_action |= DO_MAKE_XREFS;
  925.         course_of_action &= ~DO_MAKE_DOCUMENT;
  926.       }
  927.       else RB_Panic("you must specify a xref file with the GENXREF option\n");
  928.     }
  929.     else RB_Panic("unknown option \"%s\"\n", *parameter);
  930.   }
  931.  
  932.   if ((course_of_action & DO_USE_XREFS) && (output_mode == ASCII || output_mode == LATEX))
  933.   {
  934.     printf("%s: WARNING, you can not use xrefs when you generate\n"
  935.            "\t\tdocumentation in ASCII or LaTeX [discarding switch]\n", argv[0]);
  936.     course_of_action &= ~DO_USE_XREFS;
  937.   }
  938. }
  939.  
  940. /*** RB_Analyse_Arguments ***/
  941.  
  942.  
  943. /****** RoboDoc.c/RB_Analyse_Xrefs [3.0b]
  944.  * NAME
  945.  *   RB_Analyse_Xrefs -- scan the xref files.
  946.  * SYNOPSIS
  947.  *   RB_Analyse_Xrefs (xreffiles_file)
  948.  *   RB_Analyse_Xrefs (FILE *)
  949.  * FUNCTION
  950.  *   Scan the file xreffiles_file. This file contains the
  951.  *   names of one or more xref files. All the references in the
  952.  *   files are scaned and stored in a link list of the type
  953.  *   RB_link.
  954.  *   These xref files can be generated with robodoc.
  955.  * INPUTS
  956.  *   xreffiles_file - a file pointer to the file with xref file
  957.  *   names.
  958.  * RESULT
  959.  *   none
  960.  * BUGS
  961.  *   Might fail if there are syntax errors in one of the xref
  962.  *   files.
  963.  * SEE ALSO
  964.  *   RB_Generate_xrefs, RB_Add_Link
  965.  * SOURCE
  966.  */
  967.  
  968. void RB_Analyse_Xrefs(FILE * xreffiles_file)
  969. {
  970.   while(!feof(xreffiles_file))
  971.   {
  972.     fgets(line_buffer, MAX_LINE_LEN, xreffiles_file);
  973.     if (!feof(xreffiles_file))
  974.     {
  975.       char *cur_char;
  976.       cur_char = line_buffer; find_eol ;
  977.       if (*cur_char == '\n') *cur_char = '\0';
  978.       if ((xref_file = fopen(line_buffer, "r")) != NULL)
  979.       {
  980.         int xrefs_found  = FALSE;
  981.         int end_of_xrefs = FALSE;
  982.  
  983.         while(!feof(xref_file) && !xrefs_found)
  984.         {
  985.           fgets(line_buffer, MAX_LINE_LEN, xref_file);
  986.           if (!feof(xref_file) && !strncmp("XREF:", line_buffer, 5))
  987.             xrefs_found = TRUE;
  988.         }
  989.  
  990.         while(!feof(xref_file) && !end_of_xrefs)
  991.         {
  992.           fgets(line_buffer, MAX_LINE_LEN, xref_file);
  993.           if (!feof(xref_file))
  994.           {
  995.             cur_char = line_buffer; find_quote ;
  996.             if (*cur_char == '\"') RB_Add_Link();
  997.             else end_of_xrefs = TRUE;
  998.           }
  999.         }
  1000.         fclose(xref_file);
  1001.         xref_file = NULL;
  1002.       }
  1003.       else RB_Panic("could not open xref file \"%s\"\n", line_buffer);
  1004.     }
  1005.   }
  1006. }
  1007.  
  1008. /*** RB_Analyse_Xrefs */
  1009.  
  1010.  
  1011. /****i* RoboDoc.c/RB_Add_Link [3.0b]
  1012.  * NAME
  1013.  *   RB_Add_Link -- add a reference link to the list
  1014.  * SYNOPSIS
  1015.  *   void RB_Add_Link ()
  1016.  * FUNCTION
  1017.  *   Adds a reference from a xref file to the linked list
  1018.  *   with references.
  1019.  * INPUTS
  1020.  *   Uses the global variable line_buffer and first_link.
  1021.  * NOTES
  1022.  *   Makes sneaky use of the function RB_Insert_In_List.
  1023.  * SEE ALSO
  1024.  *   RB_Analyse_Xrefs, RB_link.
  1025.  * SOURCE
  1026.  */
  1027.  
  1028. void RB_Add_Link()
  1029. {
  1030.   char *label_name, *file_name;
  1031.   struct RB_link *new_link;
  1032.   char *cur_char = line_buffer;
  1033.   find_quote ; label_name = ++cur_char; find_quote ; *cur_char++ = '\0';
  1034.   find_quote ; file_name  = ++cur_char; find_quote ; *cur_char = '\0';
  1035.   RB_Say("adding xref link \"%s\"->\"%s\"\n", label_name, file_name);
  1036.  
  1037.   new_link = RB_Alloc_Link(label_name, file_name);
  1038.   RB_Insert_In_List((struct RB_header **)&first_link,
  1039.                     (struct RB_header *)new_link);
  1040. }
  1041.  
  1042. /*** RB_Add_Link ***/
  1043.  
  1044.  
  1045. /****** RoboDoc.c/RB_Analyse_Document [3.0i]
  1046.  * NAME
  1047.  *   RB_Analyse_Document -- scan document for headers and store them
  1048.  * SYNOPSIS
  1049.  *   RB_Analyse_Document (document)
  1050.  *   RB_Analyse_Document (FILE *)
  1051.  * FUNCTION
  1052.  *   Searches the document for headers. Stores information about
  1053.  *   any headers that are found in a linked list. Information
  1054.  *   that is stored includes, the name of the header, its version
  1055.  *   number, and its contents.
  1056.  * INPUTS
  1057.  *   document - a pointer to a file with the document to be
  1058.  *              analysed
  1059.  *   the gobal buffer line_buffer.
  1060.  * RESULT
  1061.  *   1)   A linked list pointed to by the global variable
  1062.  *        first_header that contains information about each
  1063.  *        header.
  1064.  * NOTES
  1065.  *   Using fseek and ftell because gcc doesn't know fgetpos and fsetpos,
  1066.  *   on the sun unix system that I use
  1067.  * SEE ALSO
  1068.  *   RB_Find_Marker
  1069.  * SOURCE
  1070.  */
  1071.  
  1072. void RB_Analyse_Document (FILE * document)
  1073. {
  1074.   int header_type;
  1075.   int real_size;
  1076.   char *name ;
  1077.  
  1078.   for (;
  1079.        (header_type = RB_Find_Marker(document)) != NO_HEADER ;
  1080.       )
  1081.   {
  1082.     long cur_file_pos;
  1083.     struct RB_header *new_header;
  1084.     if (!
  1085.         (
  1086.          ((header_type == INTERNAL_HEADER) && !(course_of_action & (DO_INCLUDE_INTERNAL | DO_INTERNAL_ONLY)))
  1087.          ||
  1088.          ((header_type != INTERNAL_HEADER) && (course_of_action & DO_INTERNAL_ONLY))
  1089.          ||
  1090.          (header_type == BLANK_HEADER)
  1091.         )
  1092.        )
  1093.     {
  1094.       new_header = RB_Alloc_Header();
  1095.       RB_Insert_In_List(&first_header, new_header);
  1096.       new_header->type = header_type;
  1097.       if ((new_header->name = RB_Find_Header_Name()) != NULL)
  1098.       {
  1099.         RB_Say("found header [line %5d]: \"%s\"\n", line_number, new_header->name);
  1100.         new_header->function_name = RB_FilePart(new_header->name);
  1101.         cur_file_pos = (long)ftell(document);
  1102.         if ((real_size = RB_Find_End_Marker(document, &new_header->size)) != 0)
  1103.         {
  1104.           char *contents;
  1105.  
  1106.           fseek(document, cur_file_pos, 0);
  1107.           if ((contents = (char *)malloc((new_header->size + 2) * sizeof(char))) != NULL)
  1108.           {
  1109.             fread(contents, new_header->size, sizeof(char), document);
  1110.             contents[real_size]  = '\0';
  1111.             new_header->contents = contents;
  1112.             new_header->size     = real_size;
  1113.           } else RB_Panic("out of memory! [Alloc Header Contents]\n");
  1114.         }
  1115.         else
  1116.         {
  1117.           RB_Panic("found header with no end marker \"%s\"\n", new_header->name);
  1118.         }
  1119.       }
  1120.       else
  1121.       {
  1122.         RB_Panic("found header marker but no name [line %d]\n", line_number);
  1123.       }
  1124.     }
  1125.     else
  1126.     {
  1127.       if (header_type != BLANK_HEADER)
  1128.       {
  1129.         if ((name = RB_Find_Header_Name()) != NULL)
  1130.         {
  1131.           if ((real_size = RB_Find_End_Marker(document, &new_header->size)) == 0)
  1132.           {
  1133.             RB_Panic("found header with no end marker \"%s\"\n", name);
  1134.           }
  1135.         }
  1136.         else
  1137.         {
  1138.           RB_Panic("found header marker but no name [line %d]\n", line_number);
  1139.         }
  1140.       }
  1141.     }
  1142.   }
  1143. }
  1144.  
  1145. /*** RB_Analyse_Document ***/
  1146.  
  1147.  
  1148. /****** RoboDoc.c/RB_Find_Marker [3.0h]
  1149.  * NAME
  1150.  *   RB_Find_Marker -- Search for header marker in document.
  1151.  * SYNOPSIS
  1152.  *   header_type = RB_Find_Marker (document)
  1153.  *             int RB_Find_Marker (FILE *)
  1154.  * FUNCTION
  1155.  *   Read document file line by line, and search each line for the
  1156.  *   any of the headers defined in the array  header_markers
  1157.  * INPUTS
  1158.  *   document - pointer to the file to be searched.
  1159.  *   the gobal buffer line_buffer.
  1160.  * RESULT
  1161.  *   header type
  1162.  *   can be:
  1163.  *    (1) NO_HEADER - no header found, end of file reached
  1164.  *    (2) MAIN_HEADER
  1165.  *    (3) GENERIC_HEADER
  1166.  *    (4) INTERNAL_HEADER
  1167.  * SEE ALSO
  1168.  *   RB_Find_End_Marker
  1169.  * SOURCE
  1170.  */
  1171.  
  1172. int RB_Find_Marker(FILE * document)
  1173. {
  1174.   int found;
  1175.   int marker, marker_type ;
  1176.   char *cur_char, *cur_mchar ;
  1177.  
  1178.   found = FALSE ;
  1179.   while( !feof(document) && !found)
  1180.   {
  1181.     *line_buffer = '\0';
  1182.     fgets(line_buffer, MAX_LINE_LEN, document);
  1183.     if (!feof(document))
  1184.     {
  1185.       line_number++;
  1186.       for (marker=0 ;
  1187.            ((cur_mchar = header_markers[marker]) != NULL) && !found ;
  1188.            marker++)
  1189.       {
  1190.         for (found = TRUE, cur_char = line_buffer;
  1191.              *cur_mchar && *cur_char && found;
  1192.               cur_mchar++, cur_char++)
  1193.         {
  1194.           if (*cur_mchar != *cur_char) found = FALSE ;
  1195.         }
  1196.       }
  1197.       if (found)
  1198.       {
  1199.         switch (*cur_char)
  1200.         {
  1201.           case 'h': marker_type = MAIN_HEADER ;     break ;
  1202.           case '*': marker_type = GENERIC_HEADER ;  break ;
  1203.           case 'i': marker_type = INTERNAL_HEADER ; break ;
  1204.           default:
  1205.             RB_Say("%s: WARNING, [line %d] undefined headertype, using GENERIC\n",
  1206.                     whoami, line_number);
  1207.             marker_type = GENERIC_HEADER;
  1208.         }
  1209.       }
  1210.     }
  1211.   }
  1212.   if (!found || feof(document)) return (NO_HEADER) ;
  1213.  
  1214.   if (marker_type == GENERIC_HEADER)
  1215.   {
  1216.     skip_while (*cur_char == '*') ;
  1217.     if (*cur_char == '/')
  1218.       return BLANK_HEADER;
  1219.   }
  1220.  
  1221.   return marker_type;
  1222. }
  1223.  
  1224. /*** RB_Find_Marker ***/
  1225.  
  1226.  
  1227. /****** RoboDoc.c/RB_Find_End_Marker [3.0h]
  1228.  * NAME
  1229.  *   RB_Find_End_Marker -- Search for end marker in document.
  1230.  * SYNOPSIS
  1231.  *   result = RB_Find_End_Marker (document)
  1232.  *        int RB_Find_End_Marker (FILE *)
  1233.  * FUNCTION
  1234.  *   Searches line by line till any of the markers in the
  1235.  *   array: end_markers is found.
  1236.  * INPUTS
  1237.  *   document   - pointer to the file to be searched.
  1238.  *   int *total_size - external size
  1239.  *   the gobal buffer line_buffer.
  1240.  * RESULT
  1241.  *                real_size if end marker was found
  1242.  *   0          - no end marker was found
  1243.  * SEE ALSO
  1244.  *   RB_Find_Marker
  1245.  * SOURCE
  1246.  */
  1247.  
  1248. int RB_Find_End_Marker(FILE * document, int *total_size)
  1249. {
  1250.   int real_size = 0;
  1251.   int found = FALSE ;
  1252.   int marker ;
  1253.   int   line_len;
  1254.   char *cur_char, *cur_mchar ;
  1255.  
  1256.   while (!feof(document) && !found)
  1257.   {
  1258.     cur_char = line_buffer;
  1259.     *cur_char  = '\0';
  1260.     fgets(cur_char, MAX_LINE_LEN, document);
  1261.     ++line_number;                  /* global linecounter *koessi*/
  1262.  
  1263.     line_len   = strlen(cur_char);
  1264.     real_size += line_len;
  1265.  
  1266.     if (!feof(document))
  1267.     {
  1268.       for (marker=0 ;
  1269.            ((cur_mchar = end_markers[marker]) != NULL) && !found ;
  1270.            marker++)
  1271.       {
  1272.         for (found = TRUE, cur_char = line_buffer;
  1273.              *cur_mchar && *cur_char && found;
  1274.               cur_mchar++, cur_char++)
  1275.         {
  1276.           if (*cur_mchar != *cur_char) found = FALSE ;
  1277.         }
  1278.       }
  1279.     }
  1280.   }
  1281.   if (total_size)
  1282.       *total_size = real_size ;
  1283.   if (found) return (real_size - line_len) ;
  1284.   else return(0);
  1285. }
  1286.  
  1287. /*** RB_Find_End_Marker ***/
  1288.  
  1289.  
  1290. /****** RoboDoc.c/RB_Find_Header_Name   [3.0b]
  1291.  * NAME
  1292.  *   RB_Find_Header_Name -- search for header name
  1293.  * SYNOPSIS
  1294.  *   result = RB_Find_Header_Name ()
  1295.  *      char *RB_Find_Header_Name ()
  1296.  * FUNCTION
  1297.  *   Searches the line buffer for the header name.
  1298.  *   It assumes that the header name follows after the
  1299.  *   header marker, seperated by one or more spaces, and terminated
  1300.  *   by one or more spaces or a '\n'.
  1301.  *   It allocates an array of chars and copies the name to this array.
  1302.  * INPUTS
  1303.  *   the gobal buffer line_buffer.
  1304.  * RESULT
  1305.  *   pointer to the allocated array of chars that contains the name,
  1306.  *   terminated with a '\0'.
  1307.  *   NULL if no header name was found.
  1308.  * MODIFICATION HISTORY
  1309.  *   8. August 1995      --  optimized by koessi
  1310.  * SEE ALSO
  1311.  *   RB_Find_Function_Name(), RB_WordLen(), RB_StrDup()
  1312.  * SOURCE
  1313.  */
  1314.  
  1315. char *RB_Find_Header_Name(void)
  1316. {
  1317.   char *cur_char;
  1318.  
  1319.   cur_char = line_buffer;
  1320.   skip_while (*cur_char != '*') ;
  1321.   skip_while (!isspace(*cur_char)) ;
  1322.   skip_while (isspace(*cur_char)) ;
  1323.   if (*cur_char)
  1324.   {
  1325.     char *end_char, old_char ;
  1326.     end_char  = cur_char + RB_WordLen(cur_char);
  1327.     old_char  = *end_char;
  1328.     *end_char = '\0';
  1329.     cur_char  = RB_StrDup(cur_char);
  1330.     *end_char = old_char;
  1331.     return (cur_char);
  1332.   }
  1333.   return(NULL);
  1334. }
  1335.  
  1336. /*** RB_Find_Header_Name ***/
  1337.  
  1338.  
  1339. /****** RoboDoc.c/RB_Find_Item [3.0b]
  1340.  * NAME
  1341.  *   RB_Find_Item -- find item in header contents.
  1342.  * SYNOPSIS
  1343.  *   item_type = RB_Find_Item (next_line,item_line)
  1344.  *
  1345.  *           int RB_Find_Item (char **,  char **)
  1346.  * FUNCTION
  1347.  *   Searches the header contents line by line, looking
  1348.  *   for an item Indicator.
  1349.  * INPUTS
  1350.  *   next_line  - pointer to a pointer that points to line
  1351.  *                at which the search will start.
  1352.  * SIDE-EFFECTS
  1353.  *   next_line  - pointer to a pointer that points to begin of the line
  1354.  *                after the line the item was found on.
  1355.  *   item_line  - pointer to a pointer that points to the line the item
  1356.  *                was found on.
  1357.  * RESULT
  1358.  *   item_type  - one of possible items indicators.
  1359.  * SOURCE
  1360.  */
  1361.  
  1362. int RB_Find_Item (char **next_line,char **item_line)
  1363. {
  1364.   char *cur_char = *next_line ;
  1365.   int item_type ;
  1366.  
  1367.   for(item_type = NO_ITEM;
  1368.       *cur_char && (item_type == NO_ITEM);
  1369.      )
  1370.   {
  1371.     *item_line = cur_char ;
  1372.     cur_char = RB_Skip_Remark_Marker (cur_char) ;
  1373.  
  1374.     skip_while (isspace(*cur_char) && *cur_char != '\n') ;
  1375.     if (isupper(*cur_char))
  1376.     {
  1377.       char *item_begin = cur_char ;
  1378.       char *item_end ;
  1379.  
  1380.       skip_while (isupper(*cur_char)) ;
  1381.       item_end = cur_char ;
  1382.       if (isspace(*cur_char) && *cur_char)
  1383.       {
  1384.         skip_while (isspace(*cur_char) && *cur_char != '\n') ;
  1385.  
  1386.         /* Item consists of two words ? */
  1387.         if (isupper(*cur_char) && *cur_char)
  1388.         {
  1389.           skip_while (isupper(*cur_char)) ;
  1390.           item_end = cur_char ;
  1391.           skip_while (isspace(*cur_char) && *cur_char != '\n') ;
  1392.         }
  1393.         if (*cur_char == '\n')
  1394.         {
  1395.           char old_char = *item_end ;
  1396.  
  1397.           *item_end = '\0' ;
  1398.           item_type = RB_Get_Item_Type(item_begin);
  1399.           *item_end = old_char ;
  1400.           cur_char++ ;
  1401.         }
  1402.       }
  1403.     }
  1404.     if (item_type == NO_ITEM)
  1405.     {
  1406.       find_eol ; if (*cur_char) cur_char++ ;
  1407.     }
  1408.   }
  1409.  
  1410.   /* advance item_line to end of comment block when we have no more items */
  1411.   if (item_type == NO_ITEM) {
  1412.     *item_line = cur_char ;
  1413.   }
  1414.  
  1415.   *next_line = cur_char ;
  1416.   return item_type ;
  1417. }
  1418.  
  1419. /*** RB_Find_Item ***/
  1420.  
  1421.  
  1422. /****** RoboDoc.c/RB_Generate_xrefs [2.0]
  1423.  * NAME
  1424.  *   RB_Generate_xrefs
  1425.  * SYNOPSIS
  1426.  *   RB_Generate_xrefs (dest_doc, source_name, dest_name)
  1427.  *
  1428.  *   RB_Generate_xrefs (FILE *, char *, char *)
  1429.  * FUNCTION
  1430.  *   Generates a xref file for the document that has been
  1431.  *   analysed by robodoc.
  1432.  * INPUTS
  1433.  *   dest_doc    - pointer to the file to which the xrefs will be
  1434.  *                 written.
  1435.  *   source_name - pointer to the name of the document that has
  1436.  *                 been analysed by robodoc
  1437.  *   dest_name   - pointer to the name of the document robodoc will
  1438.  *                 write the documentation to.
  1439.  *   first_header - global variable, the list with function
  1440.  *                 headers.
  1441.  * SEE ALSO
  1442.  * SOURCE
  1443.  */
  1444.  
  1445. void RB_Generate_xrefs(FILE * dest_doc, char *source_name, char *dest_name)
  1446. {
  1447.   struct RB_header *cur_header;
  1448.  
  1449.   fprintf(dest_doc, "/* XREF-File generated by RoboDoc v"RB_VERSION" */\n");
  1450.   fprintf(dest_doc, "\nXREF:\n");
  1451.   fprintf(dest_doc, " \"%s\" \"%s\" 0 0\n", source_name, dest_name);
  1452.   for (cur_header = first_header;
  1453.        cur_header;
  1454.        cur_header = cur_header->next_header
  1455.     )
  1456.   {
  1457.     if (cur_header->function_name)
  1458.       fprintf(dest_doc, " \"%s\" \"%s\" 0 0\n",
  1459.               cur_header->function_name, dest_name);
  1460.   }
  1461.   fprintf(dest_doc, "\n/* End of XREF-File */\n");
  1462. }
  1463.  
  1464. /*** RB_Generate_xrefs ***/
  1465.  
  1466.  
  1467. /****** RoboDoc.c/RB_Generate_Documentation [3.0h]
  1468.  * NAME
  1469.  *   RB_Generate_Documentation
  1470.  * SYNOPSIS
  1471.  *   RB_Generate_Documentation (dest_doc, name, name)
  1472.  *
  1473.  *   RB_Generate_Documentation (FILE *, char *, char *)
  1474.  * FUNCTION
  1475.  *   Generates the autodoc documentation from the list of
  1476.  *   function headers that has been created by
  1477.  *   RB_Analyse_Document.
  1478.  * INPUTS
  1479.  *   dest_doc   - Pointer to the file to which the output will be written.
  1480.  *   src_name   - The name of the source file.
  1481.  *   dest_name  - The name of this file.
  1482.  * BUGS
  1483.  *   There might be plenty.
  1484.  * SEE ALSO
  1485.  *   RB_Generate_Doc_Start,
  1486.  *   RB_Generate_Doc_End,
  1487.  *   RB_Generate_Header_Start,
  1488.  *   RB_Generate_Header_End,
  1489.  *   RB_Generate_Header_Name,
  1490.  *   RB_Generate_Item_Name,
  1491.  *   RB_Generate_Item_Doc,
  1492.  *   RB_Generate_Item_Body.
  1493.  * SOURCE
  1494.  */
  1495.  
  1496. void RB_Generate_Documentation(FILE * dest_doc, char *src_name, char *dest_name)
  1497. {
  1498.   struct RB_header *cur_header;
  1499.  
  1500.   RB_Make_Index_Tables () ;
  1501.  
  1502.   RB_Generate_Doc_Start(dest_doc, src_name, dest_name) ;
  1503.  
  1504.   for (cur_header = first_header; cur_header; cur_header = cur_header->next_header)
  1505.   {
  1506.     int   item_type;
  1507.     char *next_line, *item_line = NULL;
  1508.  
  1509.     RB_Say("generating documentation for \"%s\"\n", cur_header->name);
  1510.  
  1511.     RB_Generate_Header_Start(    dest_doc, cur_header);
  1512. /*  RB_Generate_Header_Name(dest_doc, cur_header->name); */
  1513.  
  1514.     next_line = cur_header->contents;
  1515.     item_type = RB_Find_Item(&next_line, &item_line);
  1516.  
  1517.     if (item_type != NO_ITEM)
  1518.     {
  1519.       int   old_item_type;
  1520.       char *old_next_line;
  1521.  
  1522.       do {
  1523.         if (course_of_action & DO_TELL)
  1524.           printf("[%s] ", item_names[item_type]);
  1525.  
  1526.         RB_Generate_Item_Name(dest_doc, item_type);
  1527.  
  1528.         old_next_line = next_line;
  1529.         old_item_type = item_type;
  1530.  
  1531.         item_type = RB_Find_Item(&next_line, &item_line);
  1532.  
  1533.         RB_Generate_Item_Doc(dest_doc, dest_name,
  1534.                              old_next_line, item_line,
  1535.                              cur_header->function_name, old_item_type);
  1536.       } while(item_type != NO_ITEM);
  1537.       if (course_of_action & DO_TELL) putchar('\n') ;
  1538.     }
  1539.     else
  1540.       printf("%s: WARNING, header \"%s\" has no items\n", whoami, cur_header->name);
  1541.  
  1542.     RB_Generate_Header_End(dest_doc, cur_header);
  1543.   }
  1544.   RB_Generate_Doc_End(dest_doc, dest_name);
  1545. }
  1546.  
  1547. /*** RB_Generate_Documentation ***/
  1548.  
  1549.  
  1550. /****** RoboDoc.c/RB_Generate_Doc_Start [3.0h]
  1551.  * NAME
  1552.  *   RB_Generate_Doc_Start -- Generate document header.
  1553.  * SYNOPSIS
  1554.  *   RB_Generate_Doc_Start (dest_doc, src_name, name)
  1555.  *
  1556.  *   RB_Generate_Doc_Start (FILE *, char *, char *)
  1557.  * FUNCTION
  1558.  *   Generates for depending on the output_mode the text that
  1559.  *   will be at the start of a document.
  1560.  *   Including the table of contents.
  1561.  * INPUTS
  1562.  *   dest_doc - pointer to the file to which the output will
  1563.  *              be written.
  1564.  *   src_name - the name of the source file.
  1565.  *   name     - the name of this file.
  1566.  *   output_mode - global variable that indicates the output
  1567.  *                 mode.
  1568.  * SEE ALSO
  1569.  *   RB_Generate_Doc_End
  1570.  * SOURCE
  1571.  */
  1572.  
  1573. void RB_Generate_Doc_Start(FILE * dest_doc, char *src_name, char *name)
  1574. {
  1575.   struct  RB_header *cur_header;
  1576.   int     cur_len, max_len, header_nr;
  1577.  
  1578.   switch(output_mode)
  1579.   {
  1580.     case  AMIGAGUIDE:
  1581.       if (strstr(name + 1, ".guide") == NULL)
  1582.         fprintf(dest_doc, "@database %s.guide\n", name);
  1583.       else
  1584.         fprintf(dest_doc, "@database %s\n", name);
  1585.       fprintf(dest_doc, "@rem Source: %s\n", src_name);
  1586.       fprintf(dest_doc, "@rem " COMMENT_ROBODOC);
  1587.       fprintf(dest_doc, "@rem " COMMENT_COPYRIGHT);
  1588.       fprintf(dest_doc, "@node Main %s\n", name);
  1589.       fprintf(dest_doc, "@{jcenter}\n");
  1590.       fprintf(dest_doc, "@{fg highlight}@{b}TABLE OF CONTENTS@{ub}@{fg text}\n\n");
  1591.  
  1592.       max_len = 0;
  1593.       for (cur_header = first_header;
  1594.            cur_header;
  1595.            cur_header = cur_header->next_header)
  1596.       {
  1597.         if (cur_header->name)
  1598.         {
  1599.           cur_len = strlen(cur_header->name);
  1600.           if (cur_len > max_len)  max_len = cur_len;
  1601.         }
  1602.       }
  1603.  
  1604.       for (cur_header = first_header;
  1605.            cur_header;
  1606.            cur_header = cur_header->next_header)
  1607.       {
  1608.         if (cur_header->name && cur_header->function_name)
  1609.         {
  1610.           fprintf(dest_doc, "@{\"%s", cur_header->name);
  1611.  
  1612.           for (cur_len = strlen(cur_header->name);
  1613.                cur_len < max_len;
  1614.                ++cur_len) fputc(' ', dest_doc);
  1615.             fprintf(dest_doc, "\" Link \"%s\"}\n", cur_header->function_name);
  1616.         }
  1617.       }
  1618.  
  1619.       fprintf(dest_doc, "@{jleft}\n");
  1620.       fprintf(dest_doc, "@endnode\n");
  1621.       break;
  1622.  
  1623.     case HTML:
  1624.       fprintf(dest_doc, "<HTML><HEAD>\n<TITLE>%s</TITLE>\n<!--\n  Source: %s\n", name, src_name);
  1625.       fprintf(dest_doc, "  " COMMENT_ROBODOC);
  1626.       fprintf(dest_doc, "  " COMMENT_COPYRIGHT);
  1627.       fprintf(dest_doc, "-->\n</HEAD><BODY>\n");
  1628.       fprintf(dest_doc, "<CENTER><H2>TABLE OF CONTENTS</H2></CENTER>\n");
  1629. #if 0
  1630.       fprintf(dest_doc, "<p><OL>\n");
  1631. #else
  1632.       /* this fixes the ragged output in Lynx */
  1633.       fprintf(dest_doc, "<p><OL><br>\n");
  1634. #endif
  1635.       for (cur_header = first_header;
  1636.            cur_header;
  1637.            cur_header = cur_header->next_header)
  1638.       {
  1639.         if (cur_header->name && cur_header->function_name)
  1640.           fprintf(dest_doc, "<A HREF=\"#%s\">%s</A><br>\n",
  1641.                   cur_header->function_name, cur_header->name);
  1642.       }
  1643.       fprintf(dest_doc, "</OL>\n");
  1644.       break;
  1645.  
  1646.     case LATEX:
  1647.       fprintf(dest_doc, "%% Document: %s\n", name);
  1648.       fprintf(dest_doc, "%% Source: %s\n", src_name);
  1649.       fprintf(dest_doc, "%% " COMMENT_ROBODOC);
  1650.       fprintf(dest_doc, "%% " COMMENT_COPYRIGHT);
  1651.       fprintf(dest_doc, "\\documentstyle{article}\n");
  1652.       fprintf(dest_doc, "\\setlength{\\topmargin}{0in}\n");
  1653.       fprintf(dest_doc, "\\setlength{\\textwidth}{6.5in}\n");
  1654.       fprintf(dest_doc, "\\setlength{\\parindent}{0in}\n");
  1655.       fprintf(dest_doc, "\\setlength{\\parskip}{.08in}\n\n");
  1656.  
  1657.       /* changed default header to use boldface (vs slant) */
  1658.       fprintf(dest_doc, "\\pagestyle{myheadings}\n");
  1659.       fprintf(dest_doc, "\\markright{\\bf \\protect\\thesection \\hskip 1em"
  1660.                         "\\relax API Reference}\n\n");
  1661.  
  1662.       fprintf(dest_doc, "\\begin{document}\n");
  1663.       fprintf(dest_doc, "\\section{API Reference}\n"
  1664.                         "This section is your complete reference to the "
  1665.                         "functions and concepts for this system.\n");
  1666.  
  1667.       /* autogenerate table of contents! */
  1668.       fprintf(dest_doc, "\\tableofcontents\n");
  1669.       fprintf(dest_doc, "\\newpage\n");
  1670.  
  1671.       /* trick to disable the autogenerated \newpage */
  1672.       fputc('%', dest_doc);
  1673.       break;
  1674.  
  1675.     case RTF:
  1676.       {
  1677.         char *cook_link;
  1678.  
  1679.         /* RTF header */
  1680.         fprintf(dest_doc, "{\\rtf1\\ansi \\deff0"
  1681.                               "{\\fonttbl;"
  1682.                                   "\\f0\\fswiss MS Sans Serif;"
  1683.                                   "\\f1\\fmodern Courier New;"
  1684.                                   "\\f2\\ftech Symbol;"
  1685.                               "}"
  1686.                               "{\\colortbl;"
  1687.                                   "\\red255\\green255\\blue255;"
  1688.                                   "\\red0\\green0\\blue0;"
  1689.                                   "\\red0\\green0\\blue255;"
  1690.                               "}");
  1691.  
  1692.         /* RTF document info */
  1693.         fprintf(dest_doc,     "{\\info"
  1694.                                   "{\\title %s}"
  1695.                                   "{\\comment\n"
  1696.                                   " Source: %s\n"
  1697.                                   " " COMMENT_ROBODOC
  1698.                                   " " COMMENT_COPYRIGHT
  1699.                                   "}"
  1700.                               "}", name, src_name);
  1701.  
  1702.         /* RTF document format */
  1703.         fprintf(dest_doc, "{\\margl1440\\margr1440}\n");
  1704.  
  1705.         /* RTF document section */
  1706.         fprintf(dest_doc, "\\f0\\cb1\\cf3\\fs28\\b1\\qc" 
  1707.                           "{\\super #{\\footnote{\\super #}%s_TOC}}"
  1708.                           "{\\super ${\\footnote{\\super $}Contents}}"
  1709.                           "{TABLE OF CONTENTS}\\ql\\b0\\fs20\\cf2\\par\n", src_name);
  1710.         for (cur_header = first_header;
  1711.              cur_header;
  1712.              cur_header = cur_header->next_header)
  1713.         {
  1714.           if (cur_header->name && cur_header->function_name) {
  1715.             cook_link = RB_CookStr(cur_header->function_name);
  1716.             fprintf(dest_doc, "{\\uldb %s}{\\v %s}\\line\n",
  1717.                    cur_header->name, cook_link);
  1718.             free(cook_link);
  1719.           }
  1720.         }
  1721.         fprintf(dest_doc, "\\par\n");
  1722.       }
  1723.       break;
  1724.     case ASCII:
  1725.       if (course_of_action & DO_TOC)
  1726.       {
  1727.         fprintf(dest_doc, "TABLE OF CONTENTS\n");
  1728.         for (cur_header = first_header, header_nr = 1;
  1729.              cur_header;
  1730.              cur_header = cur_header->next_header, header_nr++)
  1731.         {
  1732.           if (cur_header->name && cur_header->function_name)
  1733.           {
  1734.             fprintf(dest_doc, "%4.4d %s\n", header_nr, cur_header->name);
  1735.           }
  1736.         }
  1737.         fputc('\f', dest_doc);
  1738.       }
  1739.  
  1740.     default: break;
  1741.   }
  1742. }
  1743.  
  1744. /*** RB_Generate_Doc_Start ***/
  1745.  
  1746.  
  1747. /****** RoboDoc.c/RB_Generate_Doc_End [3.0h]
  1748.  * NAME
  1749.  *   RB_Generate_Doc_End -- generate document trailer.
  1750.  * SYNOPSIS
  1751.  *   RB_Generate_Doc_End (dest_doc, name)
  1752.  *
  1753.  *   RB_Generate_Doc_End (FILE *, char *)
  1754.  * FUNCTION
  1755.  *   Generates for depending on the output_mode the text that
  1756.  *   will be at the end of a document.
  1757.  * INPUTS
  1758.  *   dest_doc - pointer to the file to which the output will
  1759.  *              be written.
  1760.  *   name     - the name of this file.
  1761.  *   output_mode - global variable that indicates the output
  1762.  *                 mode.
  1763.  * NOTES
  1764.  *   Doesn't do anything with its arguments, but that might
  1765.  *   change in the future.
  1766.  * BUGS
  1767.  * SOURCE
  1768.  */
  1769.  
  1770. void RB_Generate_Doc_End(FILE * dest_doc, char *name)
  1771. {
  1772.   switch(output_mode)
  1773.   {
  1774.     case AMIGAGUIDE: fputc('\n', dest_doc); break;
  1775.     case HTML:  fprintf(dest_doc, "</BODY></HTML>\n"); break;
  1776.     case LATEX: fprintf(dest_doc, "\\end{document}\n"); break;
  1777.     case RTF:   fputc('}', dest_doc); break ;
  1778.     case ASCII: break ;
  1779.   }
  1780. }
  1781.  
  1782. /*** RB_Generate_Doc_End ***/
  1783.  
  1784.  
  1785. /****** RoboDoc.c/RB_Generate_Header_Start [3.0h]
  1786.  * NAME
  1787.  *   RB_Generate_Header_Start -- generate header start text.
  1788.  * SYNOPSIS
  1789.  *  void RB_Generate_Header_Start (dest_doc, cur_header)
  1790.  *
  1791.  *  void RB_Generate_Header_Start (FILE *, struct RB_header *)
  1792.  * FUNCTION
  1793.  *   Generates depending on the output_mode the text that
  1794.  *   will be at the end of each header.
  1795.  * INPUTS
  1796.  *   dest_doc - pointer to the file to which the output will
  1797.  *              be written.
  1798.  *   cur_header - pointer to a RB_header structure.
  1799.  * SEE ALSO
  1800.  *   RB_Generate_Header_End
  1801.  * SOURCE
  1802.  */
  1803.  
  1804. void RB_Generate_Header_Start (FILE * dest_doc, struct RB_header *cur_header)
  1805. {
  1806.   char *cook_link;
  1807.  
  1808.   switch(output_mode)        /* switch by *koessi*/
  1809.   {
  1810.     case AMIGAGUIDE:
  1811.       if (cur_header->name && cur_header->function_name)
  1812.       {
  1813.         fprintf(dest_doc, "@Node \"%s\" \"%s\"\n",
  1814.                 cur_header->function_name,
  1815.                 cur_header->name);
  1816.         fprintf(dest_doc, "%s", att_start_command[MAKE_SHINE][output_mode]);
  1817.         fprintf(dest_doc, "%s", cur_header->name);
  1818.         fprintf(dest_doc, "%s", att_stop_command[MAKE_SHINE][output_mode]);
  1819.         fprintf(dest_doc, "\n\n") ;
  1820.       }
  1821.       break;
  1822.     case HTML:
  1823.       if (cur_header->name && cur_header->function_name)
  1824.       {
  1825.         fprintf(dest_doc, "<HR>\n");
  1826.         fprintf(dest_doc, "\n<A NAME=%s><H3>%s</H3></A>\n\n",
  1827.                 cur_header->function_name,
  1828.                 cur_header->name);
  1829.       }
  1830.       break;
  1831.     case LATEX:
  1832.       cook_link = RB_CookStr(cur_header->name);
  1833.       fprintf(dest_doc, "\\newpage\n");
  1834.       fprintf(dest_doc, "\\subsection{%s}\n", cook_link);
  1835.       free(cook_link);
  1836.       break;
  1837.     case RTF:
  1838.       if (cur_header->name && cur_header->function_name)
  1839.       {
  1840.         cook_link = RB_CookStr(cur_header->function_name);
  1841.         fprintf(dest_doc, "\\page"
  1842.                 "{\\super #{\\footnote{\\super #}%s}}"
  1843.                 "{\\super ${\\footnote{\\super $}%s}}"
  1844.                 "\\cf3 %s\\cf2\\line\n",
  1845.                 cur_header->function_name,
  1846.                 cur_header->name,
  1847.                 cur_header->name);
  1848.         free(cook_link);
  1849.       }
  1850.       break;
  1851.     case ASCII:
  1852.       {
  1853.         fprintf(dest_doc, "%s", att_start_command[MAKE_SHINE][output_mode]);
  1854.         fprintf(dest_doc, "%s", cur_header->name);
  1855.         fprintf(dest_doc, "%s", att_stop_command[MAKE_SHINE][output_mode]);
  1856.         fprintf(dest_doc, "\n\n") ;
  1857.       }
  1858.       break;
  1859.   }
  1860. }
  1861.  
  1862. /*** RB_Generate_Header_Start ***/
  1863.  
  1864.  
  1865. /****** RoboDoc.c/RB_Generate_Header_End [3.0h]
  1866.  * NAME
  1867.  *   RB_Generate_Header_End
  1868.  * SYNOPSIS
  1869.  *   void RB_Generate_Header_End (dest_doc, cur_header)
  1870.  *
  1871.  *   void RB_Generate_Header_End (FILE *, struct RB_header *)
  1872.  * FUNCTION
  1873.  *   Generates for depending on the output_mode the text that
  1874.  *   will be at the end of a header.
  1875.  * INPUTS
  1876.  *   dest_doc - pointer to the file to which the output will
  1877.  *              be written.
  1878.  *   cur_header - pointer to a RB_header structure.
  1879.  * SEE ALSO
  1880.  *   RB_Generate_Header_Start
  1881.  * SOURCE
  1882.  */
  1883.  
  1884. void RB_Generate_Header_End (FILE * dest_doc, struct RB_header *cur_header)
  1885. {
  1886.   switch(output_mode)        /* switch by *koessi*/
  1887.   {
  1888.     case AMIGAGUIDE:
  1889.       if (cur_header->name && cur_header->function_name)
  1890.         fprintf(dest_doc, "@endnode\n");
  1891.       break;
  1892.     case HTML:
  1893.     case LATEX: fputc('\n', dest_doc); break;
  1894.     case RTF:   fprintf(dest_doc, "\\par\n"); break;
  1895.     case ASCII: fputc('\f', dest_doc);
  1896.     default:  break;
  1897.   }
  1898. }
  1899.  
  1900. /*** RB_Generate_Header_End ***/
  1901.  
  1902.  
  1903. /****** RoboDoc.c/RB_Generate_Header_Name [3.0c]
  1904.  * NAME
  1905.  *   RB_Generate_Header_Name
  1906.  * SYNOPSIS
  1907.  *   RB_Generate_Header_Name (dest_doc, name)
  1908.  *
  1909.  *   RB_Generate_Header_Name (FILE *, char *)
  1910.  * INPUTS
  1911.  *  dest_doc - pointer to the file to which the output will
  1912.  *             be written.
  1913.  *  name - pointer to the header name.
  1914.  * SOURCE
  1915.  */
  1916.  
  1917. void RB_Generate_Header_Name(FILE * dest_doc, char *name)
  1918. {
  1919.   char format_str[] = "%s";
  1920.   fprintf(dest_doc, format_str, att_start_command[MAKE_SHINE][output_mode]);
  1921.   fprintf(dest_doc, format_str, name);
  1922.   fprintf(dest_doc, format_str, att_stop_command[MAKE_SHINE][output_mode]);
  1923.   fprintf(dest_doc, "\n\n");
  1924. }
  1925.  
  1926. /*** RB_Generate_Header_Name ***/
  1927.  
  1928.  
  1929. /****** RoboDoc.c/RB_Generate_Item_Name [2.01]
  1930.  * NAME
  1931.  *   RB_Generate_Item_Name -- fast&easy
  1932.  * SYNOPSIS
  1933.  *   void RB_Generate_Item_Name( FILE * dest_doc, int item_type )
  1934.  * FUNCTION
  1935.  *   write the items name to the doc
  1936.  * INPUTS
  1937.  *   FILE * dest_doc         -- document in progress
  1938.  *   int item_type           -- this leads to the name and makes colors
  1939.  * AUTHOR
  1940.  *   Koessi
  1941.  * NOTES
  1942.  *   uses globals: output_mode, item_names[]
  1943.  * SOURCE
  1944.  */
  1945.  
  1946. void RB_Generate_Item_Name(FILE * dest_doc, int item_type)
  1947. {
  1948.   char format_str[] = "%s";
  1949.  
  1950.   if (item_attributes[item_type] & ITEM_NAME_LARGE_FONT)
  1951.   {
  1952.     fprintf(dest_doc, format_str, att_start_command[MAKE_LARGE][output_mode]);
  1953.     fprintf(dest_doc, format_str, item_names[item_type]);
  1954.     fprintf(dest_doc, format_str, att_stop_command[ MAKE_LARGE][output_mode]);
  1955.   }
  1956.   else fprintf(dest_doc, format_str, item_names[item_type]);
  1957.  
  1958.   fputc('\n', dest_doc);
  1959. }
  1960.  
  1961. /*** RB_Generate_Item_Name *** Zitatende ***/
  1962.  
  1963.  
  1964. /****** RoboDoc.c/RB_Generate_Item_Doc [3.0h]
  1965.  * NAME
  1966.  *   RB_Generate_Item_Doc
  1967.  * SYNOPSIS
  1968.  *   void RB_Generate_Item_Doc(FILE * dest_doc, char *dest_name,
  1969.  *                             char *begin_of_item,
  1970.  *                             char *end_of_item,
  1971.  *                             char *function_name,
  1972.  *                             int item_type)
  1973.  * FUNCTION
  1974.  *   Generates the body text of an item, applying predefined attributes
  1975.  *   to the text.
  1976.  * NOTES
  1977.  *   Body text is always non-proportional for several reasons:
  1978.  *   1) text is rarely written with prop spacing and text wrapping
  1979.  *      in mind -- e.g., see SYNOPSIS above
  1980.  *   2) source code looks better
  1981.  *   3) it simplifies LaTeX handling
  1982.  * SOURCE
  1983.  */
  1984.  
  1985. void RB_Generate_Item_Doc(FILE * dest_doc, char *dest_name,
  1986.                           char *begin_of_item,
  1987.                           char *end_of_item,
  1988.                           char *function_name,
  1989.                           int item_type)
  1990. {
  1991.   char format_str[] = "%s";
  1992.  
  1993.   if (begin_of_item == end_of_item)
  1994.   {
  1995.     switch (output_mode)
  1996.     {
  1997.       case HTML:
  1998.         fprintf(dest_doc, "<BR>\n"); break;
  1999.       case LATEX:
  2000.         fprintf(dest_doc, "\\\\\n"); break;
  2001.       case RTF:
  2002.         fprintf(dest_doc, "\n"); break;
  2003.       default:
  2004.         break;
  2005.     }
  2006.     return;
  2007.   }
  2008.  
  2009.   if (item_attributes[item_type] & TEXT_BODY_LARGE_FONT)
  2010.     fprintf(dest_doc, format_str, att_start_command[MAKE_LARGE][output_mode]);
  2011.   if (item_attributes[item_type] & TEXT_BODY_ITALICS)
  2012.     fprintf(dest_doc, format_str, att_start_command[MAKE_ITALICS][output_mode]);
  2013.   if (item_attributes[item_type] & TEXT_BODY_NON_PROP)
  2014.     fprintf(dest_doc, format_str, att_start_command[MAKE_NON_PROP][output_mode]);
  2015.   if (item_attributes[item_type] & TEXT_BODY_SMALL_FONT)
  2016.     fprintf(dest_doc, format_str, att_start_command[MAKE_SMALL][output_mode]);
  2017.   if (item_attributes[item_type] & TEXT_BODY_BOLD)
  2018.     fprintf(dest_doc, format_str, att_start_command[MAKE_BOLD][output_mode]);
  2019.   if (item_attributes[item_type] & TEXT_BODY_UNDERLINE)
  2020.     fprintf(dest_doc, format_str, att_start_command[MAKE_UNDERLINE][output_mode]);
  2021.   if (item_attributes[item_type] & TEXT_BODY_SHINE)
  2022.     fprintf(dest_doc, format_str, att_start_command[MAKE_SHINE][output_mode]);
  2023.  
  2024.   /*
  2025.    * For some modes, the text body is always non-prop
  2026.    */
  2027.   switch (output_mode) {
  2028.     case HTML:
  2029.       fprintf(dest_doc, "<PRE>"); break;
  2030.     case LATEX:
  2031.       fprintf(dest_doc, "\\begin{verbatim}\n"); break;
  2032.     case RTF:
  2033.       fprintf(dest_doc, "{\\f1{}"); break;
  2034.     default:
  2035.       break;
  2036.   }
  2037.  
  2038.   RB_Generate_Item_Body(dest_doc, dest_name, begin_of_item, end_of_item,
  2039.                           function_name, item_type);
  2040.  
  2041.   switch (output_mode) {
  2042.     case HTML:
  2043.       fprintf(dest_doc, "</PRE>"); break;
  2044.     case LATEX:
  2045.       /* split the text so LaTeX doesn't get confused ;) */
  2046.       fprintf(dest_doc, "\\" "end{verbatim}\n"); break;
  2047.     case RTF:
  2048.       fputc('}', dest_doc);
  2049.     default:
  2050.       break;
  2051.   }
  2052.  
  2053.   if (item_attributes[item_type] & TEXT_BODY_SHINE)
  2054.     fprintf(dest_doc, format_str, att_stop_command[MAKE_SHINE][output_mode]);
  2055.   if (item_attributes[item_type] & TEXT_BODY_UNDERLINE)
  2056.     fprintf(dest_doc, format_str, att_stop_command[MAKE_UNDERLINE][output_mode]);
  2057.   if (item_attributes[item_type] & TEXT_BODY_BOLD)
  2058.     fprintf(dest_doc, format_str, att_stop_command[MAKE_BOLD][output_mode]);
  2059.   if (item_attributes[item_type] & TEXT_BODY_SMALL_FONT)
  2060.     fprintf(dest_doc, format_str, att_stop_command[MAKE_SMALL][output_mode]);
  2061.   if (item_attributes[item_type] & TEXT_BODY_NON_PROP)
  2062.     fprintf(dest_doc, format_str, att_stop_command[MAKE_NON_PROP][output_mode]);
  2063.   if (item_attributes[item_type] & TEXT_BODY_ITALICS)
  2064.     fprintf(dest_doc, format_str, att_stop_command[MAKE_ITALICS][output_mode]);
  2065.   if (item_attributes[item_type] & TEXT_BODY_LARGE_FONT)
  2066.     fprintf(dest_doc, format_str, att_stop_command[MAKE_LARGE][output_mode]);
  2067.   fputc('\n', dest_doc);
  2068. }
  2069.  
  2070. /*** RB_Generate_Item_Doc ***/
  2071.  
  2072.  
  2073. /****** RoboDoc.c/RB_Skip_Remark_Marker [2.0e]
  2074.  * NAME
  2075.  *    RB_Skip_Remark_Marker
  2076.  * SYNOPSIS
  2077.  *     text  = RB_Skip_Remark_Marker (line_buffer)
  2078.  *    char *                            char *
  2079.  * FUNCTION
  2080.  *    Scan and search for a recognized remark marker; skip past the
  2081.  *    marker to the body of the text
  2082.  ******/
  2083.  
  2084. char *RB_Skip_Remark_Marker (char *line_buffer)
  2085. {
  2086.   int marker, found ;
  2087.   char *cur_char, *cur_mchar ;
  2088.  
  2089.   found = FALSE ;
  2090.   for (marker=0 ;
  2091.        ((cur_mchar = remark_markers[marker]) != NULL) && !found ;
  2092.        marker++)
  2093.   {
  2094.     for (found = TRUE, cur_char = line_buffer;
  2095.          *cur_mchar && *cur_char && found;
  2096.           cur_mchar++, cur_char++)
  2097.     { if (*cur_mchar != *cur_char) found = FALSE ; }
  2098.   }
  2099.   return (cur_char) ;
  2100. }
  2101.  
  2102.  
  2103. /****** RoboDoc.c/RB_Generate_Item_Body [3.0h]
  2104.  * NAME
  2105.  *  RB_Generate_Item_Body
  2106.  * SYNOPSIS
  2107.  *  void RB_Generate_Item_Body(FILE * dest_doc, char *dest_name,
  2108.  *                             char *begin_of_item, char *end_of_item,
  2109.  *                             char *function_name,
  2110.  *                             int   item_type)
  2111.  *
  2112.  * FUNCTION
  2113.  *   Generates body of an item in output-specific form
  2114.  * INPUTS
  2115.  *   dest_doc      - pointer to the file to which
  2116.  *                   the output will be written.
  2117.  *   dest_name     - the name of this file.
  2118.  *   begin_of_item -
  2119.  *   end_of_item   -
  2120.  *   function_name -
  2121.  *   item_type     -
  2122.  * NOTES
  2123.  *   o almost completely rewritten by koessi
  2124.  *   o Almost completely Re-Rewritten by Slothouber :)
  2125.  * SOURCE
  2126.  */
  2127.  
  2128. void RB_Generate_Item_Body(FILE * dest_doc, char *dest_name,
  2129.                            char *begin_of_item, char *end_of_item,
  2130.                            char *function_name,
  2131.                            int   item_type)
  2132. {
  2133.   char *cur_char, old_char, c ;
  2134.  
  2135.   cur_char = begin_of_item;
  2136.  
  2137.   if (item_type == SOURCE_ITEM) {
  2138.     /* skip end_comment_marker */
  2139.     for (; *cur_char && *cur_char != '\n' ; cur_char++ )
  2140.       ;
  2141.  
  2142.     /* skip blank lines leading up to source code */
  2143.     while (*cur_char == '\n')
  2144.       cur_char++;
  2145.  
  2146.     /* trim blanks following source code */
  2147.     do {
  2148.       end_of_item--;
  2149.     } while (end_of_item > cur_char && isspace(*end_of_item));
  2150.     end_of_item++;  /* advance 1 for placement of the NUL */
  2151.   }
  2152.  
  2153.   old_char = *end_of_item;
  2154.   *end_of_item = '\0';
  2155.  
  2156.   for (; *cur_char; cur_char++)
  2157.   {
  2158.     int tb = tab_size;
  2159.     int do_search = TRUE ;
  2160.     int was_link  = FALSE;
  2161.  
  2162.     if (item_type != SOURCE_ITEM) {
  2163.       cur_char = RB_Skip_Remark_Marker(cur_char) ;
  2164.     } else {
  2165.       /* indent source */
  2166.       switch (output_mode) {
  2167.         case RTF:
  2168.           fprintf(dest_doc, "\\tab ");
  2169.           break;
  2170.  
  2171.         case AMIGAGUIDE:
  2172.         case HTML:
  2173.         case LATEX:
  2174.         default:
  2175.           fprintf(dest_doc, "    ");
  2176.       }
  2177.     }
  2178.  
  2179.     while (((c = *cur_char) != '\0') && (c != '\n'))
  2180.     {
  2181.       char *label_name, *file_name;
  2182.       int   tmp;
  2183.  
  2184.       if (!do_search)
  2185.       {
  2186.         if (!isalnum(c) && (c != '_'))
  2187.         {
  2188.           do_search = TRUE ;
  2189.         }
  2190.       }
  2191.       else
  2192.       {
  2193.         if (isalpha(c) || (c == '_'))
  2194.         {
  2195.           if ((was_link = RB_Find_Link(cur_char, &label_name, &file_name)) == FALSE)
  2196.           {
  2197.             do_search = FALSE ;
  2198.           }
  2199.         }
  2200.         else was_link = FALSE ;
  2201.       }
  2202.  
  2203.       if (!was_link)
  2204.       {
  2205.         switch(output_mode) {
  2206.           case AMIGAGUIDE:
  2207.             switch(c) {
  2208.               case '\n' : --cur_char; break;
  2209.               case '\t' : for (tb %= tab_size; tb < tab_size; ++tb)
  2210.                             fputc(' ', dest_doc) ;
  2211.                           break;
  2212.               case '@'  : fprintf(dest_doc, "\\@" );
  2213.                           tb++; break;
  2214.               case '\\' : fprintf(dest_doc, "\\\\") ;
  2215.                           tb++; break;
  2216.               default   : fputc(c, dest_doc); tb++;
  2217.             }
  2218.             break;
  2219.  
  2220.           case HTML:
  2221.             switch(c) {
  2222.               case '\n' : --cur_char; break;
  2223.               case '\t' : for (tb %= tab_size; tb < tab_size; ++tb)
  2224.                             fputc(' ', dest_doc) ;
  2225.                           break;
  2226.               case '<'  : fprintf(dest_doc, "<");
  2227.                           tb++; break;
  2228.               case '>'  : fprintf(dest_doc, ">");
  2229.                           tb++; break;
  2230.               case '&'  : fprintf(dest_doc, "&");
  2231.                           tb++; break;
  2232.               default   : fputc(c, dest_doc); tb++;
  2233.             }
  2234.             break;
  2235.  
  2236.           case LATEX:
  2237.             switch(c) {
  2238.               case '\n' : --cur_char; break;
  2239.               case '\t' : for (tb %= tab_size; tb < tab_size; ++tb)
  2240.                             fputc(' ', dest_doc) ;
  2241.                           break;
  2242. #if 0
  2243.               /* not used in LaTeX's verbatim environment */
  2244.               case '$'  :
  2245.               case '&'  :
  2246.               case '%'  :
  2247.               case '#'  :
  2248.               case '_'  :
  2249.               case '{'  :
  2250.               case '}'  : fputc('\\', dest_doc); fputc(c, dest_doc);
  2251.                           tb++; break;
  2252.               case '\\' : fprintf(dest_doc, "$\\backslash$");
  2253.                           tb++; break;
  2254.               case '~'  : fprintf(dest_doc, "$\\tilde$");
  2255.                           tb++; break;
  2256.               case '^'  : fprintf(dest_doc, "$\\,\\!^{\\sim}$");
  2257.                           tb++; break;
  2258. #endif
  2259.               default   : fputc(c, dest_doc); tb++;
  2260.             }
  2261.             break;
  2262.  
  2263.           case RTF:
  2264.             switch(c) {
  2265.               case '\n' : --cur_char; break;
  2266.               case '\t' : for (tb %= tab_size; tb < tab_size; ++tb)
  2267.                             fputc(' ', dest_doc) ;
  2268.                           break;
  2269.               case '\\' :
  2270.               case '{'  :
  2271.               case '}'  : fputc('\\', dest_doc); fputc(c, dest_doc);
  2272.                           tb++; break;
  2273.               default   : fputc(c, dest_doc); tb++;
  2274.             }
  2275.             break;
  2276.  
  2277.           default:
  2278.             fputc(c, dest_doc); tb++;
  2279.         }
  2280.         cur_char++;
  2281.       }
  2282.       else
  2283.       {
  2284.         switch(output_mode)
  2285.         {
  2286.           case AMIGAGUIDE :
  2287.             if (file_name && strcmp(file_name, dest_name))
  2288.                 fprintf(dest_doc,"@{\"%s\" Link \"%s/%s\"}",
  2289.                         label_name, file_name, label_name);
  2290.             else
  2291.             {
  2292.               if (strcmp(label_name, function_name))
  2293.                  fprintf(dest_doc,"@{\"%s\" Link \"%s\"}",
  2294.                          label_name, label_name) ;
  2295.               else
  2296.               {
  2297.                 fprintf(dest_doc,"%s",
  2298.                         att_start_command[MAKE_BOLD][output_mode]);
  2299.                 fprintf(dest_doc,"%s", label_name);
  2300.                 fprintf(dest_doc,"%s",
  2301.                         att_stop_command[MAKE_BOLD][output_mode]);
  2302.               }
  2303.             }
  2304.             break;
  2305.  
  2306.           case HTML :
  2307.             if (file_name && strcmp(file_name, dest_name))
  2308.             fprintf(dest_doc,"<A HREF=\"%s#%s\">%s</A>",
  2309.                     file_name, label_name, label_name);
  2310.             else
  2311.             {
  2312.               if (strcmp(label_name, function_name))
  2313.                   fprintf(dest_doc,"<A HREF=\"#%s\">%s</A>",
  2314.                           label_name, label_name);
  2315.               else
  2316.               {
  2317.                 fprintf(dest_doc,"%s",
  2318.                         att_start_command[MAKE_BOLD][output_mode]);
  2319.                 fprintf(dest_doc,"%s", label_name);
  2320.                 fprintf(dest_doc,"%s",
  2321.                         att_stop_command[MAKE_BOLD][output_mode]);
  2322.               }
  2323.             }
  2324.             break;
  2325.  
  2326.           case RTF :
  2327.             if (strcmp(label_name, function_name)) {
  2328.               char *cook_link;
  2329.  
  2330.               cook_link = RB_CookStr(label_name);
  2331.               fprintf(dest_doc, "{\\uldb %s}{\\v %s}",
  2332.                       label_name, cook_link);
  2333.               free(cook_link);
  2334.             } else {
  2335.               fprintf(dest_doc,"%s",
  2336.                       att_start_command[MAKE_BOLD][output_mode]);
  2337.               fprintf(dest_doc,"%s", label_name);
  2338.               fprintf(dest_doc,"%s",
  2339.                       att_stop_command[MAKE_BOLD][output_mode]);
  2340.             }
  2341.             break;
  2342.           default: fprintf(dest_doc,"%s", label_name) ;
  2343.         }
  2344.         tmp = strlen(label_name); cur_char += tmp; tb += tmp;
  2345.       } /* end if */
  2346.     }
  2347.  
  2348.     if (*cur_char) {
  2349.       if (output_mode == RTF)
  2350.         fprintf(dest_doc, "\\line");
  2351.       fputc('\n', dest_doc);
  2352.     }
  2353.   }
  2354.   *end_of_item = old_char;
  2355. }
  2356.  
  2357. /*** RB_Generate_Item_Body ***/
  2358.  
  2359.  
  2360. /****** RoboDoc.c/RB_Make_Index_Tables [3.0b]
  2361.  * NAME
  2362.  *    RB_Make_Index_Tables
  2363.  * SYNOPSIS
  2364.  *    void RB_Make_Index_Tables (void)
  2365.  * FUNCTION
  2366.  *    Creates sorted index tables of headers and links to speed up
  2367.  *    matching links later on.
  2368.  * INPUTS
  2369.  *    none
  2370.  * SIDE EFFECTS
  2371.  *    Modifies header_index & link_index
  2372.  * RESULT
  2373.  *    none
  2374.  ******/
  2375.  
  2376. void RB_Make_Index_Tables ()
  2377. {
  2378.   int nr_of_headers, header ;
  2379.   int nr_of_links, link ;
  2380.   struct RB_link    *cur_link;
  2381.   struct RB_header  *cur_header;
  2382.  
  2383.   for (cur_header = first_header, nr_of_headers = 0;
  2384.        cur_header;
  2385.        cur_header = cur_header->next_header) nr_of_headers++ ;
  2386.  
  2387.   for (cur_link = first_link, nr_of_links = 0;
  2388.        cur_link;
  2389.        cur_link = cur_link->next_link) nr_of_links++ ;
  2390.  
  2391.   if (nr_of_headers)
  2392.   {
  2393.     int sort1, sort2 ;
  2394.  
  2395.     RB_Say("Allocating Header Index Table\n");
  2396.     header_index = (struct RB_header **)malloc(nr_of_headers*sizeof(struct RB_header **)) ;
  2397.     header_index_size = nr_of_headers ;
  2398.     if (!header_index) RB_Panic ("out of memory! [Make Index Tables]\n") ;
  2399.  
  2400.     /* Fill Index Table */
  2401.     for (cur_header = first_header, header = 0;
  2402.           cur_header;
  2403.           cur_header = cur_header->next_header, header++)
  2404.         header_index[header] = cur_header ;
  2405.  
  2406.     /* Sort Index Table */
  2407.     RB_Say("Sorting Header Index Table\n");
  2408.     for (sort1 = 0; sort1 < nr_of_headers; sort1++)
  2409.     {
  2410.       struct RB_header *temp ;
  2411.       for (sort2 = sort1; sort2 < nr_of_headers; sort2++)
  2412.       {
  2413.         if (strcmp(header_index[sort1]->function_name,
  2414.                    header_index[sort2]->function_name) > 0)
  2415.         {
  2416.           temp = header_index[sort1] ;
  2417.           header_index[sort1] = header_index[sort2] ;
  2418.           header_index[sort2] = temp ;
  2419.         }
  2420.       }
  2421.     }
  2422.   }
  2423.  
  2424.   if (nr_of_links)
  2425.   {
  2426.     int sort1, sort2 ;
  2427.  
  2428.     RB_Say("Allocating Link Index Table\n");
  2429.     link_index   = (struct RB_link **)malloc(nr_of_links*sizeof(struct RB_link **)) ;
  2430.     link_index_size = nr_of_links ;
  2431.     if (!link_index) RB_Panic ("out of memory! [Make Index Tables]\n") ;
  2432.  
  2433.     /* Fill Index Table */
  2434.     for (cur_link = first_link, link = 0;
  2435.          cur_link;
  2436.          cur_link = cur_link->next_link, link++)
  2437.     {
  2438.       link_index[link] = cur_link ;
  2439.     }
  2440.  
  2441.     /* Sort Index Table */
  2442.     RB_Say("Sorting Link Index Table\n");
  2443.     for (sort1 = 0; sort1 < nr_of_links; sort1++)
  2444.     {
  2445.       struct RB_link *temp ;
  2446.       for (sort2 = sort1; sort2 < nr_of_links; sort2++)
  2447.       {
  2448.         if (strcmp(link_index[sort1]->label_name,
  2449.                    link_index[sort2]->label_name) > 0)
  2450.         {
  2451.           temp = link_index[sort1] ;
  2452.           link_index[sort1] = link_index[sort2] ;
  2453.           link_index[sort2] = temp ;
  2454.         }
  2455.       }
  2456.     }
  2457.   }
  2458. }
  2459.  
  2460.  
  2461. /****** RoboDoc.c/RB_Find_Link [3.0h]
  2462.  * NAME
  2463.  *   RB_Find_Link -- try to match word with a link
  2464.  * SYNOPSIS
  2465.  *   result = RB_Find_Link (word_begin, label_name, file_name)
  2466.  *   int      RB_Find_Link (char *,     char **,    char **)
  2467.  * FUNCTION
  2468.  *   Searches for the given word in the list of links.
  2469.  * INPUTS
  2470.  *   word_begin  - pointer to a word (a string).
  2471.  *   label_name  - pointer to a pointer to a string
  2472.  *   file_name   - pointer to a pointer to a string
  2473.  * SIDE EFFECTS
  2474.  *   label_name & file_name are modified
  2475.  * RESULT
  2476.  *   TRUE or FALSE.
  2477.  * NOTES
  2478.  *   re-rewritten by frans
  2479.  * BUGS
  2480.  * SOURCE
  2481.  */
  2482.  
  2483. int RB_Find_Link(char *word_begin, char **label_name, char **file_name)
  2484. {
  2485.   char  *cur_char, old_char ;
  2486.   int low_index, high_index, cur_index, state ;
  2487.  
  2488.   for (cur_char = word_begin ;
  2489.        isalnum(*cur_char) || (*cur_char == '_') || (*cur_char == '-')
  2490.        || (*cur_char == '.' && isalnum(*(cur_char+1))) ;
  2491.        cur_char++)
  2492.     ;
  2493.   old_char = *cur_char ;
  2494.   *cur_char = '\0' ;
  2495.  
  2496.   for (cur_index = 0, low_index = 0, high_index = header_index_size-1 ;
  2497.        high_index >= low_index ; )
  2498.   {
  2499.     cur_index = (high_index - low_index)/2 + low_index ;
  2500.     state = strcmp(word_begin, header_index[cur_index]->function_name) ;
  2501.     if (state < 0) high_index = cur_index-1 ;
  2502.     else if (state > 0) low_index = cur_index+1 ;
  2503.     else
  2504.     {
  2505.       *label_name = header_index[cur_index]->function_name ;
  2506.       *file_name  = NULL ;
  2507.       *cur_char   = old_char ;
  2508.  
  2509.       if (strlen(*label_name) > 60) RB_Panic ("Internal Error #1\n") ;
  2510.       return(TRUE) ;
  2511.     }
  2512.   }
  2513.  
  2514.   for (cur_index = 0, low_index = 0, high_index = link_index_size-1 ;
  2515.        high_index >= low_index ; )
  2516.   {
  2517.     cur_index = (high_index - low_index)/2 + low_index ;
  2518.     state = strcmp(word_begin, link_index[cur_index]->label_name) ;
  2519.     if (state < 0)
  2520.     {
  2521.       high_index = cur_index-1 ;
  2522.     }
  2523.     else if (state == 0)
  2524.     {
  2525.       *label_name = link_index[cur_index]->label_name ;
  2526.       *file_name  = link_index[cur_index]->file_name ;
  2527.       if (strlen(*label_name) > 60) RB_Panic ("Internal Error #2\n") ;
  2528.       if (strlen(*file_name) > 60)  RB_Panic ("Internal Error #3\n") ;
  2529.       *cur_char   = old_char ;
  2530.       return(TRUE) ;
  2531.     }
  2532.     else if (state > 0)
  2533.     {
  2534.       low_index = cur_index+1 ;
  2535.     }
  2536.   }
  2537.   *cur_char = old_char ;
  2538.   *file_name = NULL ;
  2539.   *label_name = NULL ;
  2540.   return(FALSE);
  2541. }
  2542.  
  2543. /*** RB_Find_Link ***/
  2544.  
  2545.  
  2546. /****** RoboDoc.c/RB_Slow_Sort [2.0]
  2547.  * NAME
  2548.  *   RB_Slow_Sort -- sort list of headers alphabetically
  2549.  * SYNOPSIS
  2550.  *   RB_Slow_Sort ()
  2551.  * FUNCTION
  2552.  *   Sorts the list of headers according to the header name
  2553.  *   in alphabetically fashion.
  2554.  * NOTES
  2555.  *   This isn't a particularly speedy way of sorting.
  2556.  * SOURCE
  2557.  */
  2558.  
  2559. void RB_Slow_Sort()
  2560. {
  2561.   struct RB_header *cur_header, *unsorted_headers, *bigger_header ;
  2562.  
  2563.   if ((unsorted_headers = first_header) != NULL)  /* additional check *koessi */
  2564.   {
  2565.     for (first_header = NULL;
  2566.          unsorted_headers->next_header; )
  2567.     {
  2568.       for (bigger_header = unsorted_headers,
  2569.            cur_header = bigger_header->next_header;
  2570.            cur_header;
  2571.            cur_header = cur_header->next_header)
  2572.       {
  2573.         if (strcmp(cur_header->name, bigger_header->name) > 0)
  2574.           bigger_header = cur_header;
  2575.       }
  2576.       RB_Remove_From_List(&unsorted_headers, bigger_header);
  2577.       RB_Insert_In_List(&first_header, bigger_header);
  2578.     }
  2579.     RB_Insert_In_List(&first_header, unsorted_headers);
  2580.   }
  2581. }
  2582.  
  2583. /*** RB_Slow_Sort ***/
  2584.  
  2585.  
  2586. /****** RoboDoc.c/RB_Insert_In_List [2.0]
  2587.  * NAME
  2588.  *   RB_Insert_In_List -- Insert a header in a list.
  2589.  * SYNOPSIS
  2590.  *   RB_Insert_In_List (anchor,new_header)
  2591.  *
  2592.  *   RB_Insert_In_List (struct RB_header **, struct RB_header *)
  2593.  * FUNCTION
  2594.  *   Insert a node in a doubly linked list.
  2595.  * INPUTS
  2596.  *   anchor     - pointer to the first node in the list.
  2597.  *   new_header - node to be inserted.
  2598.  * MODIFICATION HISTORY
  2599.  *   8. August 1995      --  optimized by koessi
  2600.  * SOURCE
  2601.  */
  2602.  
  2603. void RB_Insert_In_List(struct RB_header **anchor,
  2604.                        struct RB_header *new_header)
  2605. {
  2606.   struct RB_header *old_header;
  2607.  
  2608.   if ((old_header = *anchor) != NULL)  old_header->prev_header = new_header;
  2609.   new_header->next_header = old_header;
  2610.   new_header->prev_header = NULL;
  2611.   *anchor = new_header;
  2612. }
  2613.  
  2614. /*** RB_Insert_In_List ***/
  2615.  
  2616.  
  2617. /****** RoboDoc.c/RB_Remove_From_List [2.0]
  2618.  * NAME
  2619.  *   RB_Remove_From_List -- remove a header from a list.
  2620.  * SYNOPSIS
  2621.  *   RB_Remove_From_List (anchor, old_header)
  2622.  *   RB_Remove_From_List (struct RB_header **, struct RB_header *)
  2623.  * MODIFICATION HISTORY
  2624.  *   8. August 1995      --  optimized by koessi
  2625.  * SOURCE
  2626.  */
  2627.  
  2628. void RB_Remove_From_List(struct RB_header **anchor,
  2629.                          struct RB_header *old_header)
  2630. {
  2631.   struct RB_header *next_header = old_header->next_header;
  2632.   struct RB_header *prev_header = old_header->prev_header;
  2633.  
  2634.   if (next_header) next_header->prev_header = prev_header;
  2635.   if (prev_header) prev_header->next_header = next_header;
  2636.   else  *anchor = next_header;
  2637. }
  2638.  
  2639. /*** RB_Remove_From_List ***/
  2640.  
  2641.  
  2642. /****i* RoboDoc.c/RB_Alloc_Header [2.01]
  2643.  * NAME
  2644.  *   RB_Alloc_Header            -- oop
  2645.  * SYNOPSIS
  2646.  *   struct RB_header *RB_Alloc_Header( void )
  2647.  * FUNCTION
  2648.  *   allocate the struct RB_header
  2649.  * RESULT
  2650.  *   struct RB_header *      -- all attributes/pointers set to zero
  2651.  * AUTHOR
  2652.  *   Koessi
  2653.  * SEE ALSO
  2654.  *   RB_Free_Header()
  2655.  * SOURCE
  2656.  */
  2657.  
  2658. struct RB_header *RB_Alloc_Header(void)
  2659. {
  2660.   struct RB_header *new_header;
  2661.  
  2662.   if ((new_header = (struct RB_header *)malloc(sizeof(struct RB_header))) != NULL)
  2663.     memset(new_header, 0, sizeof(struct RB_header));
  2664.   else RB_Panic("out of memory! [Alloc Header]\n");
  2665.   return(new_header);
  2666. }
  2667.  
  2668. /*** RB_Alloc_Header ***/
  2669.  
  2670.  
  2671. /****i* RoboDoc.c/RB_Free_Header [2.01]
  2672.  * NAME
  2673.  *   RB_Free_Header             -- oop
  2674.  * SYNOPSIS
  2675.  *   void RB_Free_Header( struct RB_header *header )
  2676.  * FUNCTION
  2677.  *   free struct RB_header and associated strings
  2678.  * INPUTS
  2679.  *   struct RB_header *header -- this one
  2680.  * AUTHOR
  2681.  *   Koessi
  2682.  * SEE ALSO
  2683.  *   RB_Alloc_Header(), RB_Close_The_Shop()
  2684.  * SOURCE
  2685.  */
  2686.  
  2687. void RB_Free_Header(struct RB_header *header)
  2688. {
  2689.   if (header)
  2690.   {
  2691.     if (header->version)  free(header->version);
  2692.     if (header->name)     free(header->name);
  2693.     if (header->contents) free(header->contents);
  2694.     free(header);
  2695.   }
  2696. }
  2697.  
  2698. /*** RB_Free_Header ***/
  2699.  
  2700.  
  2701. /****i* RoboDoc.c/RB_Alloc_Link [2.01]
  2702.  * NAME
  2703.  *   RB_Alloc_Link              -- oop
  2704.  * SYNOPSIS
  2705.  *   struct RB_link *RB_Alloc_Link( char *label_name, char *file_name )
  2706.  * FUNCTION
  2707.  *   allocate struct + strings
  2708.  * INPUTS
  2709.  *   char *label_name -- strings to copy into the link
  2710.  *   char *file_name
  2711.  * RESULT
  2712.  *   struct RB_link *  -- ready-to-use
  2713.  * AUTHOR
  2714.  *   Koessi
  2715.  * SEE ALSO
  2716.  *   RB_StrDup(), RB_Free_Link()
  2717.  * SOURCE
  2718.  */
  2719.  
  2720. struct RB_link *RB_Alloc_Link(char *label_name, char *file_name)
  2721. {
  2722.   struct RB_link *new_link;
  2723.   if ((new_link = (struct RB_link *)malloc(sizeof(struct RB_link))) != NULL)
  2724.   {
  2725.     memset(new_link, 0, sizeof(struct RB_link));
  2726.  
  2727.     if (file_name) new_link->file_name = RB_StrDup(file_name);
  2728.     if (label_name) new_link->label_name = RB_StrDup(label_name);
  2729.   }
  2730.   else RB_Panic("out of memory! [Alloc Link]\n");
  2731.  
  2732.   return(new_link);
  2733. }
  2734.  
  2735. /*** RB_Alloc_Link ***/
  2736.  
  2737.  
  2738. /****i* RoboDoc.c/RB_Free_Link [2.01]
  2739.  * NAME
  2740.  *   RB_Free_Link               -- oop
  2741.  * SYNOPSIS
  2742.  *   void RB_Free_Link( struct RB_link *link )
  2743.  * FUNCTION
  2744.  *   free struct + strings
  2745.  * INPUTS
  2746.  *   struct RB_link *link
  2747.  * AUTHOR
  2748.  *   Koessi
  2749.  * SEE ALSO
  2750.  *   RB_Alloc_Link(), RB_Close_The_Shop()
  2751.  * SOURCE
  2752.  */
  2753.  
  2754. void RB_Free_Link(struct RB_link *link)
  2755. {
  2756.   if (link)
  2757.   {
  2758.     if (link->label_name) free(link->label_name);
  2759.     if (link->file_name)  free(link->file_name);
  2760.     free(link);
  2761.   }
  2762. }
  2763.  
  2764. /*** RB_Free_Link ***/
  2765.  
  2766.  
  2767. /****i* RoboDoc.c/RB_WordLen [2.01]
  2768.  * NAME
  2769.  *   RB_WordLen -- like strlen
  2770.  * SYNOPSIS
  2771.  *   int RB_WordLen( char *str )
  2772.  * FUNCTION
  2773.  *   get the amount of bytes until next space
  2774.  * INPUTS
  2775.  *   char *str -- the word
  2776.  * RESULT
  2777.  *   int -- length of the next word or 0
  2778.  * AUTHOR
  2779.  *   Koessi
  2780.  * SEE ALSO
  2781.  *   RB_Find_Header_Name()
  2782.  * SOURCE
  2783.  */
  2784.  
  2785. int RB_WordLen(char *str)
  2786. {
  2787.   int   len;
  2788.   char  c;
  2789.   for (len = 0; ((c = *str) != '\0') && !isspace(c) && (c != '\n'); ++str, ++len)
  2790.     ;
  2791.   return(len);
  2792. }
  2793.  
  2794. /*** RB_WordLen ***/
  2795.  
  2796.  
  2797. /****i* RoboDoc.c/RB_StrDup [2.01]
  2798.  * NAME
  2799.  *   RB_StrDup
  2800.  * SYNOPSIS
  2801.  *   char *RB_StrDup( char *str )
  2802.  * FUNCTION
  2803.  *   duplicate the given string
  2804.  * INPUTS
  2805.  *   char *str               -- source
  2806.  * RESULT
  2807.  *   char *                  -- destination
  2808.  * AUTHOR
  2809.  *   Koessi
  2810.  * SOURCE
  2811.  */
  2812.  
  2813. char *RB_StrDup(char *str)
  2814. {
  2815.   char *dupstr;
  2816.   if ((dupstr = (char *)malloc((strlen(str) + 1) * sizeof(char))) != NULL)
  2817.       strcpy(dupstr, str);
  2818.   else RB_Panic("out of memory! [StrDup]\n");
  2819.   return(dupstr);
  2820. }
  2821.  
  2822. /*** RB_StrDup ***/
  2823.  
  2824.  
  2825. /****i* RoboDoc.c/RB_CookStr [3.0h]
  2826.  * NAME
  2827.  *   RB_CookStr
  2828.  * SYNOPSIS
  2829.  *   char *RB_CookStr( char *str )
  2830.  * FUNCTION
  2831.  *   duplicate the given string, massaging it for the current output_mode
  2832.  * INPUTS
  2833.  *   char *str               -- source
  2834.  * RESULT
  2835.  *   char *                  -- destination
  2836.  * AUTHOR
  2837.  *   apang
  2838.  * NOTES
  2839.  *   Doesn't try/need to be as aggressive as RB_Generate_Item_Body()
  2840.  ****/
  2841.  
  2842. char *RB_CookStr(char *str)
  2843. {
  2844.   static char work_buf[MAX_LINE_LEN];
  2845.   char *cptr, c;
  2846.   int i;
  2847.  
  2848.   cptr = work_buf;
  2849.   switch (output_mode) {
  2850.     case LATEX:
  2851.       for (i = 0; ((c = *str++) != '\0') && (i < (MAX_LINE_LEN - 1)); ) {
  2852.         i++;
  2853.         if (c == '_') {
  2854.           if (i < (MAX_LINE_LEN - 1)) {
  2855.             *cptr++ = '\\'; *cptr++ = '_';
  2856.             i++;
  2857.           } else {
  2858.             break;
  2859.           }
  2860.         } else {
  2861.           *cptr++ = c;
  2862.         }
  2863.       }
  2864.       break;
  2865.  
  2866.     case RTF:
  2867.       for (; (c = *str++) != '\0'; ) {
  2868.         if (isalnum(c) || c == '.' || c == '_') {
  2869.           *cptr++ = c;
  2870.         }
  2871.       }
  2872.       break;
  2873.  
  2874.     default:
  2875.       return RB_StrDup(str);
  2876.   }
  2877.  
  2878.   *cptr = '\0';
  2879.   return RB_StrDup(work_buf);
  2880. }
  2881.  
  2882. /*** RB_CookStr ***/
  2883.  
  2884.  
  2885. /****i* RoboDoc.c/RB_Say [2.01]
  2886.  * NAME
  2887.  *   RB_Say                     -- varargs
  2888.  * SYNOPSIS
  2889.  *   void RB_Say( char *what, char *why, ... )
  2890.  * FUNCTION
  2891.  *   say what's going on
  2892.  * INPUTS
  2893.  *   char *format            -- formatstring
  2894.  *    ...                    -- parameters
  2895.  * AUTHOR
  2896.  *   Koessi
  2897.  * SOURCE
  2898.  */
  2899.  
  2900. void RB_Say(char *format, ...)
  2901. {
  2902.   va_list  ap;
  2903.   if (course_of_action & DO_TELL)
  2904.   {
  2905.     va_start(ap, format);
  2906.     printf("%s: ", whoami);
  2907.     vprintf(format, ap);
  2908.     va_end(ap);
  2909.   }
  2910. }
  2911.  
  2912. /*** RB_Say ***/
  2913.  
  2914.  
  2915. /****i* RoboDoc.c/RB_Panic [2.01]
  2916.  * NAME
  2917.  *   RB_Panic -- free resources and shut down
  2918.  * SYNOPSIS
  2919.  *   void RB_Panic( char *format, char *why, ... )
  2920.  * FUNCTION
  2921.  *   Print error message.
  2922.  *   Frees all resources used by robodoc.
  2923.  *   Terminates program
  2924.  * INPUTS
  2925.  *   char *format            -- formatstring
  2926.  *   ...                     -- parameters
  2927.  * AUTHOR
  2928.  *   Koessi
  2929.  * SOURCE
  2930.  */
  2931.  
  2932. void RB_Panic(char *format, ...)
  2933. {
  2934.   va_list  ap;
  2935.   va_start(ap, format);
  2936.   printf("%s: FATAL ERROR - ", whoami);
  2937.   vprintf(format, ap);
  2938.   printf("%s: closing down...\n", whoami);
  2939.   va_end(ap);
  2940.   RB_Close_The_Shop();
  2941.   exit(RB_RETURN_PANIC);  /* 20..100 */
  2942. }
  2943.  
  2944. /*** RB_Panic ***/
  2945.  
  2946.  
  2947. /****i* RoboDoc.c/RB_Close_The_Shop [3.0b]
  2948.  * NAME
  2949.  *   RB_Close_The_Shop -- free resources.
  2950.  * SYNOPSIS
  2951.  *   void RB_Close_The_Shop ()
  2952.  * FUNCTION
  2953.  *   Frees all resources used by robodoc.
  2954.  * BUGS
  2955.  *   Did free cur_header after advancing (zzzzz)
  2956.  * SEE ALSO
  2957.  *   RB_Free_Header(), RB_Free_Link()
  2958.  * SOURCE
  2959.  */
  2960.  
  2961. void RB_Close_The_Shop()
  2962. {
  2963.   struct RB_header  *cur_header, *tmp_header;
  2964.   struct RB_link    *cur_link,   *tmp_link;
  2965.  
  2966.   if (document)        fclose(document);
  2967.   if (dest_doc)        fclose(dest_doc);
  2968.   if (xreffiles_file)  fclose(xreffiles_file);
  2969.   if (xref_file)       fclose(xref_file);
  2970.  
  2971.   for (cur_header = first_header; cur_header; )
  2972.   {
  2973.     tmp_header = cur_header->next_header;
  2974.     RB_Free_Header(cur_header);
  2975.     cur_header = tmp_header;
  2976.   }
  2977.  
  2978.   for (cur_link = first_link; cur_link; )
  2979.   {
  2980.     tmp_link = cur_link->next_link;
  2981.     RB_Free_Link(cur_link);
  2982.     cur_link = tmp_link;
  2983.   }
  2984.  
  2985.   if (header_index)  free(header_index) ;
  2986.   if (link_index)    free(link_index) ;
  2987. }
  2988.  
  2989. /*** RB_Close_The_Shop ***/
  2990.